//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
//
// 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 parsing of all OpenMP directives and clauses.
///
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTContext.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/Basic/DiagnosticParse.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaOpenMP.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"
#include "llvm/Frontend/OpenMP/OMPAssume.h"
#include "llvm/Frontend/OpenMP/OMPContext.h"
#include <optional>

using namespace clang;
using namespace llvm::omp;

//===----------------------------------------------------------------------===//
// OpenMP declarative directives.
//===----------------------------------------------------------------------===//

namespace {
class DeclDirectiveListParserHelper final {
  SmallVector<Expr *, 4> Identifiers;
  Parser *P;
  OpenMPDirectiveKind Kind;

public:
  DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
      : P(P), Kind(Kind) {}
  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
    ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(
        P->getCurScope(), SS, NameInfo, Kind);
    if (Res.isUsable())
      Identifiers.push_back(Res.get());
  }
  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
};
} // namespace

static OpenMPDirectiveKind checkOpenMPDirectiveName(Parser &P,
                                                    SourceLocation Loc,
                                                    OpenMPDirectiveKind Kind,
                                                    StringRef Name) {
  unsigned Version = P.getLangOpts().OpenMP;
  auto [D, VR] = getOpenMPDirectiveKindAndVersions(Name);
  assert(D == Kind && "Directive kind mismatch");
  // Ignore the case Version > VR.Max: In OpenMP 6.0 all prior spellings
  // are explicitly allowed.
  if (static_cast<int>(Version) < VR.Min)
    P.Diag(Loc, diag::warn_omp_future_directive_spelling) << Name;

  return Kind;
}

static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
  static const DirectiveNameParser DirParser;

  const DirectiveNameParser::State *S = DirParser.initial();

  Token Tok = P.getCurToken();
  if (Tok.isAnnotation())
    return OMPD_unknown;

  std::string Concat = P.getPreprocessor().getSpelling(Tok);
  SourceLocation Loc = Tok.getLocation();

  S = DirParser.consume(S, Concat);
  if (S == nullptr)
    return OMPD_unknown;

  while (!Tok.isAnnotation()) {
    OpenMPDirectiveKind DKind = S->Value;
    Tok = P.getPreprocessor().LookAhead(0);
    if (!Tok.isAnnotation()) {
      std::string TS = P.getPreprocessor().getSpelling(Tok);
      S = DirParser.consume(S, TS);
      if (S == nullptr)
        return checkOpenMPDirectiveName(P, Loc, DKind, Concat);
      Concat += ' ' + TS;
      P.ConsumeToken();
    }
  }

  assert(S && "Should have exited early");
  return checkOpenMPDirectiveName(P, Loc, S->Value, Concat);
}

static DeclarationName parseOpenMPReductionId(Parser &P) {
  Token Tok = P.getCurToken();
  Sema &Actions = P.getActions();
  OverloadedOperatorKind OOK = OO_None;
  // Allow to use 'operator' keyword for C++ operators
  bool WithOperator = false;
  if (Tok.is(tok::kw_operator)) {
    P.ConsumeToken();
    Tok = P.getCurToken();
    WithOperator = true;
  }
  switch (Tok.getKind()) {
  case tok::plus: // '+'
    OOK = OO_Plus;
    break;
  case tok::minus: // '-'
    OOK = OO_Minus;
    break;
  case tok::star: // '*'
    OOK = OO_Star;
    break;
  case tok::amp: // '&'
    OOK = OO_Amp;
    break;
  case tok::pipe: // '|'
    OOK = OO_Pipe;
    break;
  case tok::caret: // '^'
    OOK = OO_Caret;
    break;
  case tok::ampamp: // '&&'
    OOK = OO_AmpAmp;
    break;
  case tok::pipepipe: // '||'
    OOK = OO_PipePipe;
    break;
  case tok::identifier: // identifier
    if (!WithOperator)
      break;
    [[fallthrough]];
  default:
    P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
    P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                Parser::StopBeforeMatch);
    return DeclarationName();
  }
  P.ConsumeToken();
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
                        : DeclNames.getCXXOperatorName(OOK);
}

Parser::DeclGroupPtrTy
Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(
          diag::err_expected_lparen_after,
          getOpenMPDirectiveName(OMPD_declare_reduction, OMPVersion).data())) {
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  DeclarationName Name = parseOpenMPReductionId(*this);
  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  // Consume ':'.
  bool IsCorrect = !ExpectAndConsume(tok::colon);

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  IsCorrect = IsCorrect && !Name.isEmpty();

  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
    Diag(Tok.getLocation(), diag::err_expected_type);
    IsCorrect = false;
  }

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
  // Parse list of types until ':' token.
  do {
    ColonProtectionRAIIObject ColonRAII(*this);
    SourceRange Range;
    TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS);
    if (TR.isUsable()) {
      QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(
          Range.getBegin(), TR);
      if (!ReductionType.isNull()) {
        ReductionTypes.push_back(
            std::make_pair(ReductionType, Range.getBegin()));
      }
    } else {
      SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }

    if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
      break;

    // Consume ','.
    if (ExpectAndConsume(tok::comma)) {
      IsCorrect = false;
      if (Tok.is(tok::annot_pragma_openmp_end)) {
        Diag(Tok.getLocation(), diag::err_expected_type);
        return DeclGroupPtrTy();
      }
    }
  } while (Tok.isNot(tok::annot_pragma_openmp_end));

  if (ReductionTypes.empty()) {
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  // Consume ':'.
  if (ExpectAndConsume(tok::colon))
    IsCorrect = false;

  if (Tok.is(tok::annot_pragma_openmp_end)) {
    Diag(Tok.getLocation(), diag::err_expected_expression);
    return DeclGroupPtrTy();
  }

  DeclGroupPtrTy DRD =
      Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveStart(
          getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,
          AS);

  // Parse <combiner> expression and then parse initializer if any for each
  // correct type.
  unsigned I = 0, E = ReductionTypes.size();
  for (Decl *D : DRD.get()) {
    TentativeParsingAction TPA(*this);
    ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
                                    Scope::CompoundStmtScope |
                                    Scope::OpenMPDirectiveScope);
    // Parse <combiner> expression.
    Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
    ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
        ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
    Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerEnd(
        D, CombinerResult.get());

    if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
        Tok.isNot(tok::annot_pragma_openmp_end)) {
      TPA.Commit();
      IsCorrect = false;
      break;
    }
    IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
    ExprResult InitializerResult;
    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
      // Parse <initializer> expression.
      if (Tok.is(tok::identifier) &&
          Tok.getIdentifierInfo()->isStr("initializer")) {
        ConsumeToken();
      } else {
        Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
        TPA.Commit();
        IsCorrect = false;
        break;
      }
      // Parse '('.
      BalancedDelimiterTracker T(*this, tok::l_paren,
                                 tok::annot_pragma_openmp_end);
      IsCorrect =
          !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
          IsCorrect;
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
                                        Scope::CompoundStmtScope |
                                        Scope::OpenMPDirectiveScope);
        // Parse expression.
        VarDecl *OmpPrivParm =
            Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart(
                getCurScope(), D);
        // Check if initializer is omp_priv <init_expr> or something else.
        if (Tok.is(tok::identifier) &&
            Tok.getIdentifierInfo()->isStr("omp_priv")) {
          ConsumeToken();
          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
        } else {
          InitializerResult = Actions.ActOnFinishFullExpr(
              ParseAssignmentExpression().get(), D->getLocation(),
              /*DiscardedValue*/ false);
        }
        Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerEnd(
            D, InitializerResult.get(), OmpPrivParm);
        if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
            Tok.isNot(tok::annot_pragma_openmp_end)) {
          TPA.Commit();
          IsCorrect = false;
          break;
        }
        IsCorrect =
            !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
      }
    }

    ++I;
    // Revert parsing if not the last type, otherwise accept it, we're done with
    // parsing.
    if (I != E)
      TPA.Revert();
    else
      TPA.Commit();
  }
  return Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveEnd(
      getCurScope(), DRD, IsCorrect);
}

void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
  // Parse declarator '=' initializer.
  // If a '==' or '+=' is found, suggest a fixit to '='.
  if (isTokenEqualOrEqualTypo()) {
    ConsumeToken();

    if (Tok.is(tok::code_completion)) {
      cutOffParsing();
      Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),
                                                       OmpPrivParm);
      Actions.FinalizeDeclaration(OmpPrivParm);
      return;
    }

    PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
    ExprResult Init = ParseInitializer();

    if (Init.isInvalid()) {
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/false);
    }
  } else if (Tok.is(tok::l_paren)) {
    // Parse C++ direct initializer: '(' expression-list ')'
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();

    ExprVector Exprs;

    SourceLocation LParLoc = T.getOpenLocation();
    auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
      QualType PreferredType =
          Actions.CodeCompletion().ProduceConstructorSignatureHelp(
              OmpPrivParm->getType()->getCanonicalTypeInternal(),
              OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
      CalledSignatureHelp = true;
      return PreferredType;
    };
    if (ParseExpressionList(Exprs, [&] {
          PreferredType.enterFunctionArgument(Tok.getLocation(),
                                              RunSignatureHelp);
        })) {
      if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
        RunSignatureHelp();
      Actions.ActOnInitializerError(OmpPrivParm);
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
    } else {
      // Match the ')'.
      SourceLocation RLoc = Tok.getLocation();
      if (!T.consumeClose())
        RLoc = T.getCloseLocation();

      ExprResult Initializer =
          Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
      Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
                                   /*DirectInit=*/true);
    }
  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
    // Parse C++0x braced-init-list.
    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

    ExprResult Init(ParseBraceInitializer());

    if (Init.isInvalid()) {
      Actions.ActOnInitializerError(OmpPrivParm);
    } else {
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
                                   /*DirectInit=*/true);
    }
  } else {
    Actions.ActOnUninitializedDecl(OmpPrivParm);
  }
}

Parser::DeclGroupPtrTy
Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
  bool IsCorrect = true;
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
  // Parse '('
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(
          diag::err_expected_lparen_after,
          getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion).data())) {
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  // Parse <mapper-identifier>
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
  DeclarationName MapperId;
  if (PP.LookAhead(0).is(tok::colon)) {
    if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
      Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
      IsCorrect = false;
    } else {
      MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
    }
    ConsumeToken();
    // Consume ':'.
    ExpectAndConsume(tok::colon);
  } else {
    // If no mapper identifier is provided, its name is "default" by default
    MapperId =
        DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
  }

  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
    return DeclGroupPtrTy();

  // Parse <type> <var>
  DeclarationName VName;
  QualType MapperType;
  SourceRange Range;
  TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
  if (ParsedType.isUsable())
    MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),
                                                               ParsedType);
  if (MapperType.isNull())
    IsCorrect = false;
  if (!IsCorrect) {
    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  // Consume ')'.
  IsCorrect &= !T.consumeClose();
  if (!IsCorrect) {
    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
    return DeclGroupPtrTy();
  }

  Scope *OuterScope = getCurScope();
  // Enter scope.
  DeclarationNameInfo DirName;
  SourceLocation Loc = Tok.getLocation();
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
  ParseScope OMPDirectiveScope(this, ScopeFlags);
  Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,
                                       getCurScope(), Loc);

  // Add the mapper variable declaration.
  ExprResult MapperVarRef =
      Actions.OpenMP().ActOnOpenMPDeclareMapperDirectiveVarDecl(
          getCurScope(), MapperType, Range.getBegin(), VName);

  // Parse map clauses.
  SmallVector<OMPClause *, 6> Clauses;
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    OpenMPClauseKind CKind = Tok.isAnnotation()
                                 ? OMPC_unknown
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
    Actions.OpenMP().StartOpenMPClause(CKind);
    OMPClause *Clause =
        ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
    if (Clause)
      Clauses.push_back(Clause);
    else
      IsCorrect = false;
    // Skip ',' if any.
    if (Tok.is(tok::comma))
      ConsumeToken();
    Actions.OpenMP().EndOpenMPClause();
  }
  if (Clauses.empty()) {
    Diag(Tok, diag::err_omp_expected_clause)
        << getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion);
    IsCorrect = false;
  }

  // This needs to be called within the scope because
  // processImplicitMapsWithDefaultMappers may add clauses when analyzing nested
  // types. The scope used for calling ActOnOpenMPDeclareMapperDirective,
  // however, needs to be the outer one, otherwise declared mappers don't become
  // visible.
  DeclGroupPtrTy DG = Actions.OpenMP().ActOnOpenMPDeclareMapperDirective(
      OuterScope, Actions.getCurLexicalContext(), MapperId, MapperType,
      Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
  // Exit scope.
  Actions.OpenMP().EndOpenMPDSABlock(nullptr);
  OMPDirectiveScope.Exit();
  if (!IsCorrect)
    return DeclGroupPtrTy();

  return DG;
}

TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
                                                   DeclarationName &Name,
                                                   AccessSpecifier AS) {
  // Parse the common declaration-specifiers piece.
  Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
  DeclSpec DS(AttrFactory);
  ParseSpecifierQualifierList(DS, AS, DSC);

  // Parse the declarator.
  DeclaratorContext Context = DeclaratorContext::Prototype;
  Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
  ParseDeclarator(DeclaratorInfo);
  Range = DeclaratorInfo.getSourceRange();
  if (DeclaratorInfo.getIdentifier() == nullptr) {
    Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
    return true;
  }
  Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();

  return Actions.OpenMP().ActOnOpenMPDeclareMapperVarDecl(getCurScope(),
                                                          DeclaratorInfo);
}

/// Parses 'omp begin declare variant' directive.
// The syntax is:
// { #pragma omp begin declare variant clause }
// <function-declaration-or-definition-sequence>
// { #pragma omp end declare variant }
//
bool Parser::ParseOpenMPDeclareBeginVariantDirective(SourceLocation Loc) {
  OMPTraitInfo *ParentTI =
      Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
  ASTContext &ASTCtx = Actions.getASTContext();
  OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
  if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
    while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
      ;
    // Skip the last annot_pragma_openmp_end.
    (void)ConsumeAnnotationToken();
    return true;
  }

  // Skip last tokens.
  skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);

  ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);

  VariantMatchInfo VMI;
  TI.getAsVariantMatchInfo(ASTCtx, VMI);

  std::function<void(StringRef)> DiagUnknownTrait = [this,
                                                     Loc](StringRef ISATrait) {
    // TODO Track the selector locations in a way that is accessible here
    // to improve the diagnostic location.
    Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
  };
  TargetOMPContext OMPCtx(
      ASTCtx, std::move(DiagUnknownTrait),
      /* CurrentFunctionDecl */ nullptr,
      /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>(),
      Actions.OpenMP().getOpenMPDeviceNum());

  if (isVariantApplicableInContext(VMI, OMPCtx,
                                   /*DeviceOrImplementationSetOnly=*/true)) {
    Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
    return false;
  }

  // Elide all the code till the matching end declare variant was found.
  unsigned Nesting = 1;
  SourceLocation DKLoc;
  OpenMPDirectiveKind DK = OMPD_unknown;
  do {
    DKLoc = Tok.getLocation();
    DK = parseOpenMPDirectiveKind(*this);
    if (DK == OMPD_end_declare_variant)
      --Nesting;
    else if (DK == OMPD_begin_declare_variant)
      ++Nesting;
    if (!Nesting || isEofOrEom())
      break;
    ConsumeAnyToken();
  } while (true);

  parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, DK,
                       Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
  return false;
}

namespace {
/// RAII that recreates function context for correct parsing of clauses of
/// 'declare simd' construct.
/// OpenMP, 2.8.2 declare simd Construct
/// The expressions appearing in the clauses of this directive are evaluated in
/// the scope of the arguments of the function declaration or definition.
class FNContextRAII final {
  Parser &P;
  Sema::CXXThisScopeRAII *ThisScope;
  Parser::MultiParseScope Scopes;
  bool HasFunScope = false;
  FNContextRAII() = delete;
  FNContextRAII(const FNContextRAII &) = delete;
  FNContextRAII &operator=(const FNContextRAII &) = delete;

public:
  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
    Decl *D = *Ptr.get().begin();
    NamedDecl *ND = dyn_cast<NamedDecl>(D);
    RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
    Sema &Actions = P.getActions();

    // Allow 'this' within late-parsed attributes.
    ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
                                           ND && ND->isCXXInstanceMember());

    // If the Decl is templatized, add template parameters to scope.
    // FIXME: Track CurTemplateDepth?
    P.ReenterTemplateScopes(Scopes, D);

    // If the Decl is on a function, add function parameters to the scope.
    if (D->isFunctionOrFunctionTemplate()) {
      HasFunScope = true;
      Scopes.Enter(Scope::FnScope | Scope::DeclScope |
                   Scope::CompoundStmtScope);
      Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
    }
  }
  ~FNContextRAII() {
    if (HasFunScope)
      P.getActions().ActOnExitFunctionContext();
    delete ThisScope;
  }
};
} // namespace

/// Parses clauses for 'declare simd' directive.
///    clause:
///      'inbranch' | 'notinbranch'
///      'simdlen' '(' <expr> ')'
///      { 'uniform' '(' <argument_list> ')' }
///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
static bool parseDeclareSimdClauses(
    Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
    SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
    SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
    SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
  SourceRange BSRange;
  const Token &Tok = P.getCurToken();
  bool IsError = false;
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    if (Tok.isNot(tok::identifier))
      break;
    OMPDeclareSimdDeclAttr::BranchStateTy Out;
    IdentifierInfo *II = Tok.getIdentifierInfo();
    StringRef ClauseName = II->getName();
    // Parse 'inranch|notinbranch' clauses.
    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
            << ClauseName
            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
        IsError = true;
      }
      BS = Out;
      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
      P.ConsumeToken();
    } else if (ClauseName == "simdlen") {
      if (SimdLen.isUsable()) {
        unsigned OMPVersion = P.getActions().getLangOpts().OpenMP;
        P.Diag(Tok, diag::err_omp_more_one_clause)
            << getOpenMPDirectiveName(OMPD_declare_simd, OMPVersion)
            << ClauseName << 0;
        IsError = true;
      }
      P.ConsumeToken();
      SourceLocation RLoc;
      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
      if (SimdLen.isInvalid())
        IsError = true;
    } else {
      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
      if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
          CKind == OMPC_linear) {
        SemaOpenMP::OpenMPVarListDataTy Data;
        SmallVectorImpl<Expr *> *Vars = &Uniforms;
        if (CKind == OMPC_aligned) {
          Vars = &Aligneds;
        } else if (CKind == OMPC_linear) {
          Data.ExtraModifier = OMPC_LINEAR_val;
          Vars = &Linears;
        }

        P.ConsumeToken();
        if (P.ParseOpenMPVarList(OMPD_declare_simd,
                                 getOpenMPClauseKind(ClauseName), *Vars, Data))
          IsError = true;
        if (CKind == OMPC_aligned) {
          Alignments.append(Aligneds.size() - Alignments.size(),
                            Data.DepModOrTailExpr);
        } else if (CKind == OMPC_linear) {
          assert(0 <= Data.ExtraModifier &&
                 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
                 "Unexpected linear modifier.");
          if (P.getActions().OpenMP().CheckOpenMPLinearModifier(
                  static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
                  Data.ExtraModifierLoc))
            Data.ExtraModifier = OMPC_LINEAR_val;
          LinModifiers.append(Linears.size() - LinModifiers.size(),
                              Data.ExtraModifier);
          Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
        }
      } else
        // TODO: add parsing of other clauses.
        break;
    }
    // Skip ',' if any.
    if (Tok.is(tok::comma))
      P.ConsumeToken();
  }
  return IsError;
}

Parser::DeclGroupPtrTy
Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
                                   CachedTokens &Toks, SourceLocation Loc) {
  PP.EnterToken(Tok, /*IsReinject*/ true);
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
                      /*IsReinject*/ true);
  // Consume the previously pushed token.
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);

  FNContextRAII FnContext(*this, Ptr);
  OMPDeclareSimdDeclAttr::BranchStateTy BS =
      OMPDeclareSimdDeclAttr::BS_Undefined;
  ExprResult Simdlen;
  SmallVector<Expr *, 4> Uniforms;
  SmallVector<Expr *, 4> Aligneds;
  SmallVector<Expr *, 4> Alignments;
  SmallVector<Expr *, 4> Linears;
  SmallVector<unsigned, 4> LinModifiers;
  SmallVector<Expr *, 4> Steps;
  bool IsError =
      parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
                              Alignments, Linears, LinModifiers, Steps);
  skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
  // Skip the last annot_pragma_openmp_end.
  SourceLocation EndLoc = ConsumeAnnotationToken();
  if (IsError)
    return Ptr;
  return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(
      Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
      LinModifiers, Steps, SourceRange(Loc, EndLoc));
}

namespace {
/// Constant used in the diagnostics to distinguish the levels in an OpenMP
/// contexts: selector-set={selector(trait, ...), ...}, ....
enum OMPContextLvl {
  CONTEXT_SELECTOR_SET_LVL = 0,
  CONTEXT_SELECTOR_LVL = 1,
  CONTEXT_TRAIT_LVL = 2,
};

static StringRef stringLiteralParser(Parser &P) {
  ExprResult Res = P.ParseStringLiteralExpression(true);
  return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
}

static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
                                       OMPContextLvl Lvl) {
  if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
    llvm::SmallString<16> Buffer;
    StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
    (void)P.ConsumeToken();
    return Name;
  }

  if (tok::isStringLiteral(Tok.getKind()))
    return stringLiteralParser(P);

  P.Diag(Tok.getLocation(),
         diag::warn_omp_declare_variant_string_literal_or_identifier)
      << Lvl;
  return "";
}

static bool checkForDuplicates(Parser &P, StringRef Name,
                               SourceLocation NameLoc,
                               llvm::StringMap<SourceLocation> &Seen,
                               OMPContextLvl Lvl) {
  auto Res = Seen.try_emplace(Name, NameLoc);
  if (Res.second)
    return false;

  // Each trait-set-selector-name, trait-selector-name and trait-name can
  // only be specified once.
  P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
      << Lvl << Name;
  P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
      << Lvl << Name;
  return true;
}
} // namespace

void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
                                       llvm::omp::TraitSet Set,
                                       llvm::omp::TraitSelector Selector,
                                       llvm::StringMap<SourceLocation> &Seen) {
  TIProperty.Kind = TraitProperty::invalid;

  SourceLocation NameLoc = Tok.getLocation();
  StringRef Name;
  if (Selector == llvm::omp::TraitSelector::target_device_device_num) {
    Name = "number";
    TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
    ExprResult DeviceNumExprResult = ParseExpression();
    if (DeviceNumExprResult.isUsable()) {
      Expr *DeviceNumExpr = DeviceNumExprResult.get();
      Actions.OpenMP().ActOnOpenMPDeviceNum(DeviceNumExpr);
    }
    return;
  }
  Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
  if (Name.empty()) {
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
        << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
    return;
  }

  TIProperty.RawString = Name;
  TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
  if (TIProperty.Kind != TraitProperty::invalid) {
    if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
      TIProperty.Kind = TraitProperty::invalid;
    return;
  }

  // It follows diagnosis and helping notes.
  // FIXME: We should move the diagnosis string generation into libFrontend.
  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
      << Name << getOpenMPContextTraitSelectorName(Selector)
      << getOpenMPContextTraitSetName(Set);

  TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
  if (SetForName != TraitSet::invalid) {
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
        << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
        << Name << "<selector-name>"
        << "(<property-name>)";
    return;
  }
  TraitSelector SelectorForName =
      getOpenMPContextTraitSelectorKind(Name, SetForName);
  if (SelectorForName != TraitSelector::invalid) {
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
        << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
    bool AllowsTraitScore = false;
    bool RequiresProperty = false;
    isValidTraitSelectorForTraitSet(
        SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
        AllowsTraitScore, RequiresProperty);
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
        << getOpenMPContextTraitSetName(
               getOpenMPContextTraitSetForSelector(SelectorForName))
        << Name << (RequiresProperty ? "(<property-name>)" : "");
    return;
  }
  for (const auto &PotentialSet :
       {TraitSet::construct, TraitSet::user, TraitSet::implementation,
        TraitSet::device, TraitSet::target_device}) {
    TraitProperty PropertyForName =
        getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
    if (PropertyForName == TraitProperty::invalid)
      continue;
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
        << getOpenMPContextTraitSetName(
               getOpenMPContextTraitSetForProperty(PropertyForName))
        << getOpenMPContextTraitSelectorName(
               getOpenMPContextTraitSelectorForProperty(PropertyForName))
        << ("(" + Name + ")").str();
    return;
  }
  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
      << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
}

static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
                                   OMPTraitProperty &TIProperty,
                                   OMPTraitSelector &TISelector,
                                   llvm::StringMap<SourceLocation> &Seen) {
  assert(TISelector.Kind ==
             llvm::omp::TraitSelector::implementation_extension &&
         "Only for extension properties, e.g., "
         "`implementation={extension(PROPERTY)}`");
  if (TIProperty.Kind == TraitProperty::invalid)
    return false;

  if (TIProperty.Kind ==
      TraitProperty::implementation_extension_disable_implicit_base)
    return true;

  if (TIProperty.Kind ==
      TraitProperty::implementation_extension_allow_templates)
    return true;

  if (TIProperty.Kind ==
      TraitProperty::implementation_extension_bind_to_declaration)
    return true;

  auto IsMatchExtension = [](OMPTraitProperty &TP) {
    return (TP.Kind ==
                llvm::omp::TraitProperty::implementation_extension_match_all ||
            TP.Kind ==
                llvm::omp::TraitProperty::implementation_extension_match_any ||
            TP.Kind ==
                llvm::omp::TraitProperty::implementation_extension_match_none);
  };

  if (IsMatchExtension(TIProperty)) {
    for (OMPTraitProperty &SeenProp : TISelector.Properties)
      if (IsMatchExtension(SeenProp)) {
        P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
        StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
            SeenProp.Kind, SeenProp.RawString);
        SourceLocation SeenLoc = Seen[SeenName];
        P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
            << CONTEXT_TRAIT_LVL << SeenName;
        return false;
      }
    return true;
  }

  llvm_unreachable("Unknown extension property!");
}

void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
                                     llvm::omp::TraitSet Set,
                                     llvm::StringMap<SourceLocation> &Seen) {
  assert(TISelector.Kind != TraitSelector::user_condition &&
         "User conditions are special properties not handled here!");

  SourceLocation PropertyLoc = Tok.getLocation();
  OMPTraitProperty TIProperty;
  parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);

  if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
    if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
                                TISelector, Seen))
      TIProperty.Kind = TraitProperty::invalid;

  // If we have an invalid property here we already issued a warning.
  if (TIProperty.Kind == TraitProperty::invalid) {
    if (PropertyLoc != Tok.getLocation())
      Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
          << CONTEXT_TRAIT_LVL;
    return;
  }

  if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
                                                 TISelector.Kind, Set)) {

    // If we make it here the property, selector, set, score, condition, ... are
    // all valid (or have been corrected). Thus we can record the property.
    TISelector.Properties.push_back(TIProperty);
    return;
  }

  Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
      << getOpenMPContextTraitPropertyName(TIProperty.Kind,
                                           TIProperty.RawString)
      << getOpenMPContextTraitSelectorName(TISelector.Kind)
      << getOpenMPContextTraitSetName(Set);
  Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
      << getOpenMPContextTraitPropertyName(TIProperty.Kind,
                                           TIProperty.RawString)
      << getOpenMPContextTraitSelectorName(
             getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
      << getOpenMPContextTraitSetName(
             getOpenMPContextTraitSetForProperty(TIProperty.Kind));
  Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
      << CONTEXT_TRAIT_LVL;
}

void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
                                       llvm::omp::TraitSet Set,
                                       llvm::StringMap<SourceLocation> &Seen) {
  TISelector.Kind = TraitSelector::invalid;

  SourceLocation NameLoc = Tok.getLocation();
  StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
  if (Name.empty()) {
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
        << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
    return;
  }

  TISelector.Kind = getOpenMPContextTraitSelectorKind(Name, Set);
  if (TISelector.Kind != TraitSelector::invalid) {
    if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
      TISelector.Kind = TraitSelector::invalid;
    return;
  }

  // It follows diagnosis and helping notes.
  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
      << Name << getOpenMPContextTraitSetName(Set);

  TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
  if (SetForName != TraitSet::invalid) {
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
        << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
        << Name << "<selector-name>"
        << "<property-name>";
    return;
  }
  for (const auto &PotentialSet :
       {TraitSet::construct, TraitSet::user, TraitSet::implementation,
        TraitSet::device, TraitSet::target_device}) {
    TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
        PotentialSet, TraitSelector::invalid, Name);
    if (PropertyForName == TraitProperty::invalid)
      continue;
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
        << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
        << getOpenMPContextTraitSetName(
               getOpenMPContextTraitSetForProperty(PropertyForName))
        << getOpenMPContextTraitSelectorName(
               getOpenMPContextTraitSelectorForProperty(PropertyForName))
        << ("(" + Name + ")").str();
    return;
  }
  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
      << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
}

/// Parse optional 'score' '(' <expr> ')' ':'.
static ExprResult parseContextScore(Parser &P) {
  ExprResult ScoreExpr;
  llvm::SmallString<16> Buffer;
  StringRef SelectorName =
      P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
  if (SelectorName != "score")
    return ScoreExpr;
  (void)P.ConsumeToken();
  SourceLocation RLoc;
  ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
  // Parse ':'
  if (P.getCurToken().is(tok::colon))
    (void)P.ConsumeAnyToken();
  else
    P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
        << "':'"
        << "score expression";
  return ScoreExpr;
}

void Parser::parseOMPContextSelector(
    OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
    llvm::StringMap<SourceLocation> &SeenSelectors) {
  unsigned short OuterPC = ParenCount;

  // If anything went wrong we issue an error or warning and then skip the rest
  // of the selector. However, commas are ambiguous so we look for the nesting
  // of parentheses here as well.
  auto FinishSelector = [OuterPC, this]() -> void {
    bool Done = false;
    while (!Done) {
      while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
                         tok::annot_pragma_openmp_end},
                        StopBeforeMatch))
        ;
      if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
        (void)ConsumeParen();
      if (OuterPC <= ParenCount) {
        Done = true;
        break;
      }
      if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
        Done = true;
        break;
      }
      (void)ConsumeAnyToken();
    }
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
        << CONTEXT_SELECTOR_LVL;
  };

  SourceLocation SelectorLoc = Tok.getLocation();
  parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
  if (TISelector.Kind == TraitSelector::invalid)
    return FinishSelector();

  bool AllowsTraitScore = false;
  bool RequiresProperty = false;
  if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
                                       RequiresProperty)) {
    Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
        << getOpenMPContextTraitSelectorName(TISelector.Kind)
        << getOpenMPContextTraitSetName(Set);
    Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
        << getOpenMPContextTraitSelectorName(TISelector.Kind)
        << getOpenMPContextTraitSetName(
               getOpenMPContextTraitSetForSelector(TISelector.Kind))
        << RequiresProperty;
    return FinishSelector();
  }

  if (!RequiresProperty) {
    TISelector.Properties.push_back(
        {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
         getOpenMPContextTraitSelectorName(TISelector.Kind)});
    return;
  }

  if (!Tok.is(tok::l_paren)) {
    Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
        << getOpenMPContextTraitSelectorName(TISelector.Kind)
        << getOpenMPContextTraitSetName(Set);
    return FinishSelector();
  }

  if (TISelector.Kind == TraitSelector::user_condition) {
    SourceLocation RLoc;
    ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
    if (!Condition.isUsable())
      return FinishSelector();
    TISelector.ScoreOrCondition = Condition.get();
    TISelector.Properties.push_back(
        {TraitProperty::user_condition_unknown, "<condition>"});
    return;
  }

  BalancedDelimiterTracker BDT(*this, tok::l_paren,
                               tok::annot_pragma_openmp_end);
  // Parse '('.
  (void)BDT.consumeOpen();

  SourceLocation ScoreLoc = Tok.getLocation();
  ExprResult Score = parseContextScore(*this);

  if (!AllowsTraitScore && !Score.isUnset()) {
    if (Score.isUsable()) {
      Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
          << getOpenMPContextTraitSelectorName(TISelector.Kind)
          << getOpenMPContextTraitSetName(Set) << Score.get();
    } else {
      Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
          << getOpenMPContextTraitSelectorName(TISelector.Kind)
          << getOpenMPContextTraitSetName(Set) << "<invalid>";
    }
    Score = ExprResult();
  }

  if (Score.isUsable())
    TISelector.ScoreOrCondition = Score.get();

  llvm::StringMap<SourceLocation> SeenProperties;
  do {
    parseOMPContextProperty(TISelector, Set, SeenProperties);
  } while (TryConsumeToken(tok::comma));

  // Parse ')'.
  BDT.consumeClose();
}

void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
                                  llvm::StringMap<SourceLocation> &Seen) {
  TISet.Kind = TraitSet::invalid;

  SourceLocation NameLoc = Tok.getLocation();
  StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
  if (Name.empty()) {
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
        << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
    return;
  }

  TISet.Kind = getOpenMPContextTraitSetKind(Name);
  if (TISet.Kind != TraitSet::invalid) {
    if (checkForDuplicates(*this, Name, NameLoc, Seen,
                           CONTEXT_SELECTOR_SET_LVL))
      TISet.Kind = TraitSet::invalid;
    return;
  }

  // It follows diagnosis and helping notes.
  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;

  TraitSelector SelectorForName =
      getOpenMPContextTraitSelectorKind(Name, TISet.Kind);
  if (SelectorForName != TraitSelector::invalid) {
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
        << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
    bool AllowsTraitScore = false;
    bool RequiresProperty = false;
    isValidTraitSelectorForTraitSet(
        SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
        AllowsTraitScore, RequiresProperty);
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
        << getOpenMPContextTraitSetName(
               getOpenMPContextTraitSetForSelector(SelectorForName))
        << Name << (RequiresProperty ? "(<property-name>)" : "");
    return;
  }
  for (const auto &PotentialSet :
       {TraitSet::construct, TraitSet::user, TraitSet::implementation,
        TraitSet::device, TraitSet::target_device}) {
    TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
        PotentialSet, TraitSelector::invalid, Name);
    if (PropertyForName == TraitProperty::invalid)
      continue;
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
        << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
        << getOpenMPContextTraitSetName(
               getOpenMPContextTraitSetForProperty(PropertyForName))
        << getOpenMPContextTraitSelectorName(
               getOpenMPContextTraitSelectorForProperty(PropertyForName))
        << ("(" + Name + ")").str();
    return;
  }
  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
      << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
}

void Parser::parseOMPContextSelectorSet(
    OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
  auto OuterBC = BraceCount;

  // If anything went wrong we issue an error or warning and then skip the rest
  // of the set. However, commas are ambiguous so we look for the nesting
  // of braces here as well.
  auto FinishSelectorSet = [this, OuterBC]() -> void {
    bool Done = false;
    while (!Done) {
      while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
                         tok::annot_pragma_openmp_end},
                        StopBeforeMatch))
        ;
      if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
        (void)ConsumeBrace();
      if (OuterBC <= BraceCount) {
        Done = true;
        break;
      }
      if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
        Done = true;
        break;
      }
      (void)ConsumeAnyToken();
    }
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
        << CONTEXT_SELECTOR_SET_LVL;
  };

  parseOMPTraitSetKind(TISet, SeenSets);
  if (TISet.Kind == TraitSet::invalid)
    return FinishSelectorSet();

  // Parse '='.
  if (!TryConsumeToken(tok::equal))
    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
        << "="
        << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
            "\"")
               .str();

  // Parse '{'.
  if (Tok.is(tok::l_brace)) {
    (void)ConsumeBrace();
  } else {
    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
        << "{"
        << ("'=' that follows the context set name \"" +
            getOpenMPContextTraitSetName(TISet.Kind) + "\"")
               .str();
  }

  llvm::StringMap<SourceLocation> SeenSelectors;
  do {
    OMPTraitSelector TISelector;
    parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
    if (TISelector.Kind != TraitSelector::invalid &&
        !TISelector.Properties.empty())
      TISet.Selectors.push_back(TISelector);
  } while (TryConsumeToken(tok::comma));

  // Parse '}'.
  if (Tok.is(tok::r_brace)) {
    (void)ConsumeBrace();
  } else {
    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
        << "}"
        << ("context selectors for the context set \"" +
            getOpenMPContextTraitSetName(TISet.Kind) + "\"")
               .str();
  }
}

bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
  llvm::StringMap<SourceLocation> SeenSets;
  do {
    OMPTraitSet TISet;
    parseOMPContextSelectorSet(TISet, SeenSets);
    if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
      TI.Sets.push_back(TISet);
  } while (TryConsumeToken(tok::comma));

  return false;
}

void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
                                           CachedTokens &Toks,
                                           SourceLocation Loc) {
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
  PP.EnterToken(Tok, /*IsReinject*/ true);
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
                      /*IsReinject*/ true);
  // Consume the previously pushed token.
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);

  FNContextRAII FnContext(*this, Ptr);
  // Parse function declaration id.
  SourceLocation RLoc;
  // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
  // instead of MemberExprs.
  ExprResult AssociatedFunction;
  {
    // Do not mark function as is used to prevent its emission if this is the
    // only place where it is used.
    EnterExpressionEvaluationContext Unevaluated(
        Actions, Sema::ExpressionEvaluationContext::Unevaluated);
    AssociatedFunction = ParseOpenMPParensExpr(
        getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion), RLoc,
        /*IsAddressOfOperand=*/true);
  }
  if (!AssociatedFunction.isUsable()) {
    if (!Tok.is(tok::annot_pragma_openmp_end))
      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
        ;
    // Skip the last annot_pragma_openmp_end.
    (void)ConsumeAnnotationToken();
    return;
  }

  OMPTraitInfo *ParentTI =
      Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
  ASTContext &ASTCtx = Actions.getASTContext();
  OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
  SmallVector<Expr *, 6> AdjustNothing;
  SmallVector<Expr *, 6> AdjustNeedDevicePtr;
  SmallVector<Expr *, 6> AdjustNeedDeviceAddr;
  SmallVector<OMPInteropInfo, 3> AppendArgs;
  SourceLocation AdjustArgsLoc, AppendArgsLoc;

  // At least one clause is required.
  if (Tok.is(tok::annot_pragma_openmp_end)) {
    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
        << (getLangOpts().OpenMP < 51 ? 0 : 1);
  }

  bool IsError = false;
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    OpenMPClauseKind CKind = Tok.isAnnotation()
                                 ? OMPC_unknown
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
    if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
                                     getLangOpts().OpenMP)) {
      Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
          << (getLangOpts().OpenMP < 51 ? 0 : 1);
      IsError = true;
    }
    if (!IsError) {
      switch (CKind) {
      case OMPC_match:
        IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
        break;
      case OMPC_adjust_args: {
        AdjustArgsLoc = Tok.getLocation();
        ConsumeToken();
        SemaOpenMP::OpenMPVarListDataTy Data;
        SmallVector<Expr *> Vars;
        IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
                                     Vars, Data);
        if (!IsError) {
          switch (Data.ExtraModifier) {
          case OMPC_ADJUST_ARGS_nothing:
            llvm::append_range(AdjustNothing, Vars);
            break;
          case OMPC_ADJUST_ARGS_need_device_ptr:
            llvm::append_range(AdjustNeedDevicePtr, Vars);
            break;
          case OMPC_ADJUST_ARGS_need_device_addr:
            llvm::append_range(AdjustNeedDeviceAddr, Vars);
            break;
          default:
            llvm_unreachable("Unexpected 'adjust_args' clause modifier.");
          }
        }
        break;
      }
      case OMPC_append_args:
        if (!AppendArgs.empty()) {
          Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
              << getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion)
              << getOpenMPClauseName(CKind) << 0;
          IsError = true;
        }
        if (!IsError) {
          AppendArgsLoc = Tok.getLocation();
          ConsumeToken();
          IsError = parseOpenMPAppendArgs(AppendArgs);
        }
        break;
      default:
        llvm_unreachable("Unexpected clause for declare variant.");
      }
    }
    if (IsError) {
      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
        ;
      // Skip the last annot_pragma_openmp_end.
      (void)ConsumeAnnotationToken();
      return;
    }
    // Skip ',' if any.
    if (Tok.is(tok::comma))
      ConsumeToken();
  }

  std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
      Actions.OpenMP().checkOpenMPDeclareVariantFunction(
          Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
          SourceRange(Loc, Tok.getLocation()));

  if (DeclVarData && !TI.Sets.empty())
    Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(
        DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
        AdjustNeedDevicePtr, AdjustNeedDeviceAddr, AppendArgs, AdjustArgsLoc,
        AppendArgsLoc, SourceRange(Loc, Tok.getLocation()));

  // Skip the last annot_pragma_openmp_end.
  (void)ConsumeAnnotationToken();
}

bool Parser::parseOpenMPAppendArgs(
    SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
  bool HasError = false;
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(OMPC_append_args).data()))
    return true;

  // Parse the list of append-ops, each is;
  // interop(interop-type[,interop-type]...)
  while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
    ConsumeToken();
    BalancedDelimiterTracker IT(*this, tok::l_paren,
                                tok::annot_pragma_openmp_end);
    if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
      return true;

    OMPInteropInfo InteropInfo;
    if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
      HasError = true;
    else
      InteropInfos.push_back(InteropInfo);

    IT.consumeClose();
    if (Tok.is(tok::comma))
      ConsumeToken();
  }
  if (!HasError && InteropInfos.empty()) {
    HasError = true;
    Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
    SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
              StopBeforeMatch);
  }
  HasError = T.consumeClose() || HasError;
  return HasError;
}

bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
                                               OMPTraitInfo &TI,
                                               OMPTraitInfo *ParentTI) {
  // Parse 'match'.
  OpenMPClauseKind CKind = Tok.isAnnotation()
                               ? OMPC_unknown
                               : getOpenMPClauseKind(PP.getSpelling(Tok));
  if (CKind != OMPC_match) {
    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
        << (getLangOpts().OpenMP < 51 ? 0 : 1);
    return true;
  }
  (void)ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(OMPC_match).data()))
    return true;

  // Parse inner context selectors.
  parseOMPContextSelectors(Loc, TI);

  // Parse ')'
  (void)T.consumeClose();

  if (!ParentTI)
    return false;

  // Merge the parent/outer trait info into the one we just parsed and diagnose
  // problems.
  // TODO: Keep some source location in the TI to provide better diagnostics.
  // TODO: Perform some kind of equivalence check on the condition and score
  //       expressions.
  for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
    bool MergedSet = false;
    for (OMPTraitSet &Set : TI.Sets) {
      if (Set.Kind != ParentSet.Kind)
        continue;
      MergedSet = true;
      for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
        bool MergedSelector = false;
        for (OMPTraitSelector &Selector : Set.Selectors) {
          if (Selector.Kind != ParentSelector.Kind)
            continue;
          MergedSelector = true;
          for (const OMPTraitProperty &ParentProperty :
               ParentSelector.Properties) {
            bool MergedProperty = false;
            for (OMPTraitProperty &Property : Selector.Properties) {
              // Ignore "equivalent" properties.
              if (Property.Kind != ParentProperty.Kind)
                continue;

              // If the kind is the same but the raw string not, we don't want
              // to skip out on the property.
              MergedProperty |= Property.RawString == ParentProperty.RawString;

              if (Property.RawString == ParentProperty.RawString &&
                  Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
                continue;

              if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
                Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
              } else if (Selector.ScoreOrCondition !=
                         ParentSelector.ScoreOrCondition) {
                Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
                    << getOpenMPContextTraitPropertyName(
                           ParentProperty.Kind, ParentProperty.RawString)
                    << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
                    << getOpenMPContextTraitSetName(ParentSet.Kind);
              }
            }
            if (!MergedProperty)
              Selector.Properties.push_back(ParentProperty);
          }
        }
        if (!MergedSelector)
          Set.Selectors.push_back(ParentSelector);
      }
    }
    if (!MergedSet)
      TI.Sets.push_back(ParentSet);
  }

  return false;
}

void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
                                SmallVectorImpl<OMPClause *> &Clauses,
                                SourceLocation Loc) {
  std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    OpenMPClauseKind CKind = Tok.isAnnotation()
                                 ? OMPC_unknown
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
    Actions.OpenMP().StartOpenMPClause(CKind);
    OMPClause *Clause =
        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
    SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
              StopBeforeMatch);
    SeenClauses[unsigned(CKind)] = true;
    if (Clause != nullptr)
      Clauses.push_back(Clause);
    if (Tok.is(tok::annot_pragma_openmp_end)) {
      Actions.OpenMP().EndOpenMPClause();
      break;
    }
    // Skip ',' if any.
    if (Tok.is(tok::comma))
      ConsumeToken();
    Actions.OpenMP().EndOpenMPClause();
  }
}

void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
                                         SourceLocation Loc) {
  SmallVector<std::string, 4> Assumptions;
  bool SkippedClauses = false;

  auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
    BalancedDelimiterTracker T(*this, tok::l_paren,
                               tok::annot_pragma_openmp_end);
    if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
      return;
    T.skipToEnd();
    if (IssueNote && T.getCloseLocation().isValid())
      Diag(T.getCloseLocation(),
           diag::note_omp_assumption_clause_continue_here);
  };

  /// Helper to determine which AssumptionClauseMapping (ACM) in the
  /// AssumptionClauseMappings table matches \p RawString. The return value is
  /// the index of the matching ACM into the table or -1 if there was no match.
  auto MatchACMClause = [&](StringRef RawString) {
    llvm::StringSwitch<int> SS(RawString);
    unsigned ACMIdx = 0;
    for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
      if (ACMI.StartsWith)
        SS.StartsWith(ACMI.Identifier, ACMIdx++);
      else
        SS.Case(ACMI.Identifier, ACMIdx++);
    }
    return SS.Default(-1);
  };

  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    IdentifierInfo *II = nullptr;
    SourceLocation StartLoc = Tok.getLocation();
    int Idx = -1;
    if (Tok.isAnyIdentifier()) {
      II = Tok.getIdentifierInfo();
      Idx = MatchACMClause(II->getName());
    }
    ConsumeAnyToken();

    bool NextIsLPar = Tok.is(tok::l_paren);
    // Handle unknown clauses by skipping them.
    if (Idx == -1) {
      unsigned OMPVersion = Actions.getLangOpts().OpenMP;
      Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
          << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion)
          << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
      if (NextIsLPar)
        SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
      SkippedClauses = true;
      continue;
    }
    const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
    if (ACMI.HasDirectiveList || ACMI.HasExpression) {
      // TODO: We ignore absent, contains, and holds assumptions for now. We
      //       also do not verify the content in the parenthesis at all.
      SkippedClauses = true;
      SkipBraces(II->getName(), /* IssueNote */ false);
      continue;
    }

    if (NextIsLPar) {
      Diag(Tok.getLocation(),
           diag::warn_omp_unknown_assumption_clause_without_args)
          << II;
      SkipBraces(II->getName(), /* IssueNote */ true);
    }

    assert(II && "Expected an identifier clause!");
    std::string Assumption = II->getName().str();
    if (ACMI.StartsWith)
      Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
    else
      Assumption = "omp_" + Assumption;
    Assumptions.push_back(Assumption);
  }

  Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
                                               SkippedClauses);
}

void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
  if (Actions.OpenMP().isInOpenMPAssumeScope())
    Actions.OpenMP().ActOnOpenMPEndAssumesDirective();
  else
    Diag(Loc, diag::err_expected_begin_assumes);
}

/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
///    default-clause:
///         'default' '(' 'none' | 'shared'  | 'private' | 'firstprivate' ')
///
///    proc_bind-clause:
///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
///
///    device_type-clause:
///         'device_type' '(' 'host' | 'nohost' | 'any' )'
namespace {
struct SimpleClauseData {
  unsigned Type;
  SourceLocation Loc;
  SourceLocation LOpen;
  SourceLocation TypeLoc;
  SourceLocation RLoc;
  SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
                   SourceLocation TypeLoc, SourceLocation RLoc)
      : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
};
} // anonymous namespace

static std::optional<SimpleClauseData>
parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
  const Token &Tok = P.getCurToken();
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = P.ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind).data()))
    return std::nullopt;

  unsigned Type = getOpenMPSimpleClauseType(
      Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
      P.getLangOpts());
  SourceLocation TypeLoc = Tok.getLocation();
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
      Tok.isNot(tok::annot_pragma_openmp_end))
    P.ConsumeAnyToken();

  // Parse ')'.
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();

  return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
}

void Parser::ParseOMPDeclareTargetClauses(
    SemaOpenMP::DeclareTargetContextInfo &DTCI) {
  SourceLocation DeviceTypeLoc;
  bool RequiresToOrLinkOrIndirectClause = false;
  bool HasToOrLinkOrIndirectClause = false;
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
    bool HasIdentifier = Tok.is(tok::identifier);
    if (HasIdentifier) {
      // If we see any clause we need a to or link clause.
      RequiresToOrLinkOrIndirectClause = true;
      IdentifierInfo *II = Tok.getIdentifierInfo();
      StringRef ClauseName = II->getName();
      bool IsDeviceTypeClause =
          getLangOpts().OpenMP >= 50 &&
          getOpenMPClauseKind(ClauseName) == OMPC_device_type;

      bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
                              getOpenMPClauseKind(ClauseName) == OMPC_indirect;
      if (DTCI.Indirect && IsIndirectClause) {
        unsigned OMPVersion = Actions.getLangOpts().OpenMP;
        Diag(Tok, diag::err_omp_more_one_clause)
            << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)
            << getOpenMPClauseName(OMPC_indirect) << 0;
        break;
      }
      bool IsToEnterOrLinkClause =
          OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
      assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
             "Cannot be both!");

      // Starting with OpenMP 5.2 the `to` clause has been replaced by the
      // `enter` clause.
      if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
        Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
        break;
      }
      if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
        Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
        break;
      }

      if (!IsDeviceTypeClause && !IsIndirectClause &&
          DTCI.Kind == OMPD_begin_declare_target) {
        Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
            << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
        break;
      }
      if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
        Diag(Tok, getLangOpts().OpenMP >= 52
                      ? diag::err_omp_declare_target_unexpected_clause_52
                      : diag::err_omp_declare_target_unexpected_clause)
            << ClauseName
            << (getLangOpts().OpenMP >= 51
                    ? 4
                    : getLangOpts().OpenMP >= 50 ? 2 : 1);
        break;
      }

      if (IsToEnterOrLinkClause || IsIndirectClause)
        HasToOrLinkOrIndirectClause = true;

      if (IsIndirectClause) {
        if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
          break;
        continue;
      }
      // Parse 'device_type' clause and go to next clause if any.
      if (IsDeviceTypeClause) {
        std::optional<SimpleClauseData> DevTypeData =
            parseOpenMPSimpleClause(*this, OMPC_device_type);
        if (DevTypeData) {
          if (DeviceTypeLoc.isValid()) {
            // We already saw another device_type clause, diagnose it.
            Diag(DevTypeData->Loc,
                 diag::warn_omp_more_one_device_type_clause);
            break;
          }
          switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
          case OMPC_DEVICE_TYPE_any:
            DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
            break;
          case OMPC_DEVICE_TYPE_host:
            DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
            break;
          case OMPC_DEVICE_TYPE_nohost:
            DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
            break;
          case OMPC_DEVICE_TYPE_unknown:
            llvm_unreachable("Unexpected device_type");
          }
          DeviceTypeLoc = DevTypeData->Loc;
        }
        continue;
      }
      ConsumeToken();
    }

    if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
      auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
                                          DeclarationNameInfo NameInfo) {
        NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
            getCurScope(), SS, NameInfo);
        if (!ND)
          return;
        SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
        bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
        if (!FirstMapping)
          Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
              << NameInfo.getName();
      };
      if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
                                   /*AllowScopeSpecifier=*/true))
        break;
    }

    if (Tok.is(tok::l_paren)) {
      Diag(Tok,
           diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
      break;
    }
    if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
      Diag(Tok,
           getLangOpts().OpenMP >= 52
               ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
               : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
      break;
    }

    // Consume optional ','.
    if (Tok.is(tok::comma))
      ConsumeToken();
  }

  if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
    Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);

  // For declare target require at least 'to' or 'link' to be present.
  if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
      !HasToOrLinkOrIndirectClause)
    Diag(DTCI.Loc,
         getLangOpts().OpenMP >= 52
             ? diag::err_omp_declare_target_missing_enter_or_link_clause
             : diag::err_omp_declare_target_missing_to_or_link_clause)
        << (getLangOpts().OpenMP >= 51 ? 1 : 0);

  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}

void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
  // The last seen token is annot_pragma_openmp_end - need to check for
  // extra tokens.
  if (Tok.is(tok::annot_pragma_openmp_end))
    return;

  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
      << getOpenMPDirectiveName(DKind, OMPVersion);
  while (Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();
}

void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
                                  OpenMPDirectiveKind ExpectedKind,
                                  OpenMPDirectiveKind FoundKind,
                                  SourceLocation BeginLoc,
                                  SourceLocation FoundLoc,
                                  bool SkipUntilOpenMPEnd) {
  int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;

  if (FoundKind == ExpectedKind) {
    ConsumeAnyToken();
    skipUntilPragmaOpenMPEnd(ExpectedKind);
    return;
  }

  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
  Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
      << DiagSelection;
  Diag(BeginLoc, diag::note_matching)
      << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + "'")
             .str();
  if (SkipUntilOpenMPEnd)
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}

void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
                                               OpenMPDirectiveKind EndDKind,
                                               SourceLocation DKLoc) {
  parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
                       Tok.getLocation(),
                       /* SkipUntilOpenMPEnd */ false);
  // Skip the last annot_pragma_openmp_end.
  if (Tok.is(tok::annot_pragma_openmp_end))
    ConsumeAnnotationToken();
}

Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
    AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
    DeclSpec::TST TagType, Decl *Tag) {
  assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
         "Not an OpenMP directive!");
  ParsingOpenMPDirectiveRAII DirScope(*this);
  ParenBraceBracketBalancer BalancerRAIIObj(*this);
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;

  SourceLocation Loc;
  OpenMPDirectiveKind DKind;
  if (Delayed) {
    TentativeParsingAction TPA(*this);
    Loc = ConsumeAnnotationToken();
    DKind = parseOpenMPDirectiveKind(*this);
    if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
      // Need to delay parsing until completion of the parent class.
      TPA.Revert();
      CachedTokens Toks;
      unsigned Cnt = 1;
      Toks.push_back(Tok);
      while (Cnt && Tok.isNot(tok::eof)) {
        (void)ConsumeAnyToken();
        if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
          ++Cnt;
        else if (Tok.is(tok::annot_pragma_openmp_end))
          --Cnt;
        Toks.push_back(Tok);
      }
      // Skip last annot_pragma_openmp_end.
      if (Cnt == 0)
        (void)ConsumeAnyToken();
      auto *LP = new LateParsedPragma(this, AS);
      LP->takeToks(Toks);
      getCurrentClass().LateParsedDeclarations.push_back(LP);
      return nullptr;
    }
    TPA.Commit();
  } else {
    Loc = ConsumeAnnotationToken();
    DKind = parseOpenMPDirectiveKind(*this);
  }

  switch (DKind) {
  case OMPD_threadprivate: {
    ConsumeToken();
    DeclDirectiveListParserHelper Helper(this, DKind);
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
                                  /*AllowScopeSpecifier=*/true)) {
      skipUntilPragmaOpenMPEnd(DKind);
      // Skip the last annot_pragma_openmp_end.
      ConsumeAnnotationToken();
      return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
          Loc, Helper.getIdentifiers());
    }
    break;
  }
  case OMPD_allocate: {
    ConsumeToken();
    DeclDirectiveListParserHelper Helper(this, DKind);
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
                                  /*AllowScopeSpecifier=*/true)) {
      SmallVector<OMPClause *, 1> Clauses;
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
        while (Tok.isNot(tok::annot_pragma_openmp_end)) {
          OpenMPClauseKind CKind =
              Tok.isAnnotation() ? OMPC_unknown
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
          Actions.OpenMP().StartOpenMPClause(CKind);
          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
                                                !SeenClauses[unsigned(CKind)]);
          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
                    StopBeforeMatch);
          SeenClauses[unsigned(CKind)] = true;
          if (Clause != nullptr)
            Clauses.push_back(Clause);
          if (Tok.is(tok::annot_pragma_openmp_end)) {
            Actions.OpenMP().EndOpenMPClause();
            break;
          }
          // Skip ',' if any.
          if (Tok.is(tok::comma))
            ConsumeToken();
          Actions.OpenMP().EndOpenMPClause();
        }
        skipUntilPragmaOpenMPEnd(DKind);
      }
      // Skip the last annot_pragma_openmp_end.
      ConsumeAnnotationToken();
      return Actions.OpenMP().ActOnOpenMPAllocateDirective(
          Loc, Helper.getIdentifiers(), Clauses);
    }
    break;
  }
  case OMPD_requires: {
    SourceLocation StartLoc = ConsumeToken();
    SmallVector<OMPClause *, 5> Clauses;
    llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
    if (Tok.is(tok::annot_pragma_openmp_end)) {
      Diag(Tok, diag::err_omp_expected_clause)
          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
      break;
    }
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
      OpenMPClauseKind CKind = Tok.isAnnotation()
                                   ? OMPC_unknown
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
      Actions.OpenMP().StartOpenMPClause(CKind);
      OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
                                            !SeenClauses[unsigned(CKind)]);
      SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
      SeenClauses[unsigned(CKind)] = true;
      if (Clause != nullptr)
        Clauses.push_back(Clause);
      if (Tok.is(tok::annot_pragma_openmp_end)) {
        Actions.OpenMP().EndOpenMPClause();
        break;
      }
      // Skip ',' if any.
      if (Tok.is(tok::comma))
        ConsumeToken();
      Actions.OpenMP().EndOpenMPClause();
    }
    // Consume final annot_pragma_openmp_end
    if (Clauses.empty()) {
      Diag(Tok, diag::err_omp_expected_clause)
          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
      ConsumeAnnotationToken();
      return nullptr;
    }
    ConsumeAnnotationToken();
    return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
  }
  case OMPD_error: {
    SmallVector<OMPClause *, 1> Clauses;
    SourceLocation StartLoc = ConsumeToken();
    ParseOpenMPClauses(DKind, Clauses, StartLoc);
    Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
                                               SourceLocation(),
                                               /*InExContext = */ false);
    break;
  }
  case OMPD_assumes:
  case OMPD_begin_assumes:
    ParseOpenMPAssumesDirective(DKind, ConsumeToken());
    break;
  case OMPD_end_assumes:
    ParseOpenMPEndAssumesDirective(ConsumeToken());
    break;
  case OMPD_declare_reduction:
    ConsumeToken();
    if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
      skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
      // Skip the last annot_pragma_openmp_end.
      ConsumeAnnotationToken();
      return Res;
    }
    break;
  case OMPD_declare_mapper: {
    ConsumeToken();
    if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
      // Skip the last annot_pragma_openmp_end.
      ConsumeAnnotationToken();
      return Res;
    }
    break;
  }
  case OMPD_begin_declare_variant: {
    ConsumeToken();
    if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {
      // Skip the last annot_pragma_openmp_end.
      if (!isEofOrEom())
        ConsumeAnnotationToken();
    }
    return nullptr;
  }
  case OMPD_end_declare_variant: {
    ConsumeToken();
    if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
      Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
    else
      Diag(Loc, diag::err_expected_begin_declare_variant);
    // Skip the last annot_pragma_openmp_end.
    ConsumeAnnotationToken();
    return nullptr;
  }
  case OMPD_declare_variant:
  case OMPD_declare_simd: {
    // The syntax is:
    // { #pragma omp declare {simd|variant} }
    // <function-declaration-or-definition>
    //
    CachedTokens Toks;
    Toks.push_back(Tok);
    ConsumeToken();
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
      Toks.push_back(Tok);
      ConsumeAnyToken();
    }
    Toks.push_back(Tok);
    ConsumeAnyToken();

    DeclGroupPtrTy Ptr;
    if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
                                                       TagType, Tag);
    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
      // Here we expect to see some function declaration.
      if (AS == AS_none) {
        assert(TagType == DeclSpec::TST_unspecified);
        ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
        MaybeParseCXX11Attributes(Attrs);
        ParsingDeclSpec PDS(*this);
        Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
      } else {
        Ptr =
            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
      }
    }
    if (!Ptr) {
      Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
          << (DKind == OMPD_declare_simd ? 0 : 1);
      return DeclGroupPtrTy();
    }
    if (DKind == OMPD_declare_simd)
      return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
    assert(DKind == OMPD_declare_variant &&
           "Expected declare variant directive only");
    ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
    return Ptr;
  }
  case OMPD_begin_declare_target:
  case OMPD_declare_target: {
    SourceLocation DTLoc = ConsumeAnyToken();
    bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
    SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
    if (HasClauses)
      ParseOMPDeclareTargetClauses(DTCI);
    bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
                               !HasClauses ||
                               (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);

    // Skip the last annot_pragma_openmp_end.
    ConsumeAnyToken();

    if (HasImplicitMappings) {
      Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
      return nullptr;
    }

    Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
    llvm::SmallVector<Decl *, 4> Decls;
    for (auto &It : DTCI.ExplicitlyMapped)
      Decls.push_back(It.first);
    return Actions.BuildDeclaratorGroup(Decls);
  }
  case OMPD_end_declare_target: {
    if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
      Diag(Tok, diag::err_omp_unexpected_directive)
          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
      break;
    }
    const SemaOpenMP::DeclareTargetContextInfo &DTCI =
        Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
    ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
    return nullptr;
  }
  case OMPD_assume: {
    Diag(Tok, diag::err_omp_unexpected_directive)
        << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
    break;
  }
  case OMPD_unknown:
    Diag(Tok, diag::err_omp_unknown_directive);
    break;
  default:
    switch (getDirectiveCategory(DKind)) {
    case Category::Executable:
    case Category::Meta:
    case Category::Subsidiary:
    case Category::Utility:
      Diag(Tok, diag::err_omp_unexpected_directive)
          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
      break;
    case Category::Declarative:
    case Category::Informational:
      break;
    }
  }
  while (Tok.isNot(tok::annot_pragma_openmp_end))
    ConsumeAnyToken();
  ConsumeAnyToken();
  return nullptr;
}

StmtResult Parser::ParseOpenMPExecutableDirective(
    ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
    bool ReadDirectiveWithinMetadirective) {
  assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;

  bool HasAssociatedStatement = true;
  Association Assoc = getDirectiveAssociation(DKind);

  // OMPD_ordered has None as association, but it comes in two variants,
  // the second of which is associated with a block.
  // OMPD_scan and OMPD_section are both "separating", but section is treated
  // as if it was associated with a statement, while scan is not.
  if (DKind != OMPD_ordered && DKind != OMPD_section &&
      (Assoc == Association::None || Assoc == Association::Separating)) {
    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
        ParsedStmtContext()) {
      Diag(Tok, diag::err_omp_immediate_directive)
          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
      if (DKind == OMPD_error) {
        SkipUntil(tok::annot_pragma_openmp_end);
        return StmtError();
      }
    }
    HasAssociatedStatement = false;
  }

  SourceLocation EndLoc;
  SmallVector<OMPClause *, 5> Clauses;
  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
  DeclarationNameInfo DirName;
  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;

  // Special processing for flush and depobj clauses.
  Token ImplicitTok;
  bool ImplicitClauseAllowed = false;
  if (DKind == OMPD_flush || DKind == OMPD_depobj) {
    ImplicitTok = Tok;
    ImplicitClauseAllowed = true;
  }
  ConsumeToken();
  // Parse directive name of the 'critical' directive if any.
  if (DKind == OMPD_critical) {
    BalancedDelimiterTracker T(*this, tok::l_paren,
                               tok::annot_pragma_openmp_end);
    if (!T.consumeOpen()) {
      if (Tok.isAnyIdentifier()) {
        DirName =
            DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
        ConsumeAnyToken();
      } else {
        Diag(Tok, diag::err_omp_expected_identifier_for_critical);
      }
      T.consumeClose();
    }
  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
    CancelRegion = parseOpenMPDirectiveKind(*this);
    if (Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
  }

  if (isOpenMPLoopDirective(DKind))
    ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
  if (isOpenMPSimdDirective(DKind))
    ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
  ParseScope OMPDirectiveScope(this, ScopeFlags);
  Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
                                       Loc);

  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    // If we are parsing for a directive within a metadirective, the directive
    // ends with a ')'.
    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
      while (Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeAnyToken();
      break;
    }
    bool HasImplicitClause = false;
    if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
      HasImplicitClause = true;
      // Push copy of the current token back to stream to properly parse
      // pseudo-clause OMPFlushClause or OMPDepobjClause.
      PP.EnterToken(Tok, /*IsReinject*/ true);
      PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
      ConsumeAnyToken();
    }
    OpenMPClauseKind CKind = Tok.isAnnotation()
                                 ? OMPC_unknown
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
    if (HasImplicitClause) {
      assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
      if (DKind == OMPD_flush) {
        CKind = OMPC_flush;
      } else {
        assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
        CKind = OMPC_depobj;
      }
    }
    // No more implicit clauses allowed.
    ImplicitClauseAllowed = false;
    Actions.OpenMP().StartOpenMPClause(CKind);
    HasImplicitClause = false;
    OMPClause *Clause =
        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
    SeenClauses[unsigned(CKind)] = true;
    if (Clause)
      Clauses.push_back(Clause);

    // Skip ',' if any.
    if (Tok.is(tok::comma))
      ConsumeToken();
    Actions.OpenMP().EndOpenMPClause();
  }
  // End location of the directive.
  EndLoc = Tok.getLocation();
  // Consume final annot_pragma_openmp_end.
  ConsumeAnnotationToken();

  if (DKind == OMPD_ordered) {
    // If the depend or doacross clause is specified, the ordered construct
    // is a stand-alone directive.
    for (auto CK : {OMPC_depend, OMPC_doacross}) {
      if (SeenClauses[unsigned(CK)]) {
        if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
            ParsedStmtContext()) {
          Diag(Loc, diag::err_omp_immediate_directive)
              << getOpenMPDirectiveName(DKind, OMPVersion) << 1
              << getOpenMPClauseName(CK);
        }
        HasAssociatedStatement = false;
      }
    }
  }

  if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
      !SeenClauses[unsigned(OMPC_sizes)]) {
    Diag(Loc, diag::err_omp_required_clause)
        << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";
  }

  StmtResult AssociatedStmt;
  if (HasAssociatedStatement) {
    // The body is a block scope like in Lambdas and Blocks.
    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
    // FIXME: We create a bogus CompoundStmt scope to hold the contents of
    // the captured region. Code elsewhere assumes that any FunctionScopeInfo
    // should have at least one compound statement scope within it.
    ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
    {
      Sema::CompoundScopeRAII Scope(Actions);
      AssociatedStmt = ParseStatement();

      if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
          getLangOpts().OpenMPIRBuilder)
        AssociatedStmt =
            Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
    }
    AssociatedStmt =
        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
  } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
             DKind == OMPD_target_exit_data) {
    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
    AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
                      Actions.ActOnCompoundStmt(Loc, Loc, {},
                                                /*isStmtExpr=*/false));
    AssociatedStmt =
        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
  }

  StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
      DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);

  // Exit scope.
  Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
  OMPDirectiveScope.Exit();

  return Directive;
}

StmtResult Parser::ParseOpenMPInformationalDirective(
    ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
    bool ReadDirectiveWithinMetadirective) {
  assert(isOpenMPInformationalDirective(DKind) &&
         "Unexpected directive category");

  bool HasAssociatedStatement = true;

  SmallVector<OMPClause *, 5> Clauses;
  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
  DeclarationNameInfo DirName;
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
  ParseScope OMPDirectiveScope(this, ScopeFlags);

  Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
                                       Loc);

  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
      while (Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeAnyToken();
      break;
    }

    OpenMPClauseKind CKind = Tok.isAnnotation()
                                 ? OMPC_unknown
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
    Actions.OpenMP().StartOpenMPClause(CKind);
    OMPClause *Clause =
        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
    SeenClauses[unsigned(CKind)] = true;
    if (Clause)
      Clauses.push_back(Clause);

    if (Tok.is(tok::comma))
      ConsumeToken();
    Actions.OpenMP().EndOpenMPClause();
  }

  SourceLocation EndLoc = Tok.getLocation();
  ConsumeAnnotationToken();

  StmtResult AssociatedStmt;
  if (HasAssociatedStatement) {
    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
    ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
    {
      Sema::CompoundScopeRAII Scope(Actions);
      AssociatedStmt = ParseStatement();
    }
    AssociatedStmt =
        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
  }

  StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
      DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);

  Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
  OMPDirectiveScope.Exit();

  return Directive;
}

StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
    ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
  if (!ReadDirectiveWithinMetadirective)
    assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
           "Not an OpenMP directive!");
  ParsingOpenMPDirectiveRAII DirScope(*this);
  ParenBraceBracketBalancer BalancerRAIIObj(*this);
  SourceLocation Loc = ReadDirectiveWithinMetadirective
                           ? Tok.getLocation()
                           : ConsumeAnnotationToken();
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
  if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
    Diag(Tok, diag::err_omp_unknown_directive);
    return StmtError();
  }

  StmtResult Directive = StmtError();

  bool IsExecutable = [&]() {
    if (DKind == OMPD_error) // OMPD_error is handled as executable
      return true;
    auto Res = getDirectiveCategory(DKind);
    return Res == Category::Executable || Res == Category::Subsidiary;
  }();

  if (IsExecutable) {
    Directive = ParseOpenMPExecutableDirective(
        StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
    assert(!Directive.isUnset() && "Executable directive remained unprocessed");
    return Directive;
  }

  switch (DKind) {
  case OMPD_nothing:
    ConsumeToken();
    // If we are parsing the directive within a metadirective, the directive
    // ends with a ')'.
    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
      while (Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeAnyToken();
    else
      skipUntilPragmaOpenMPEnd(DKind);
    if (Tok.is(tok::annot_pragma_openmp_end))
      ConsumeAnnotationToken();
    // return an empty statement
    return StmtEmpty();
  case OMPD_metadirective: {
    ConsumeToken();
    SmallVector<VariantMatchInfo, 4> VMIs;

    // First iteration of parsing all clauses of metadirective.
    // This iteration only parses and collects all context selector ignoring the
    // associated directives.
    TentativeParsingAction TPA(*this);
    ASTContext &ASTContext = Actions.getASTContext();

    BalancedDelimiterTracker T(*this, tok::l_paren,
                               tok::annot_pragma_openmp_end);
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
      OpenMPClauseKind CKind = Tok.isAnnotation()
                                   ? OMPC_unknown
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
      // Check if the clause is unrecognized.
      if (CKind == OMPC_unknown) {
        Diag(Tok, diag::err_omp_expected_clause) << "metadirective";
        TPA.Revert();
        SkipUntil(tok::annot_pragma_openmp_end);
        return Directive;
      }
      if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)
        Diag(Tok, diag::err_omp_unexpected_clause)
            << getOpenMPClauseName(CKind) << "metadirective";
      if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)
        Diag(Tok, diag::warn_omp_default_deprecated);

      SourceLocation Loc = ConsumeToken();

      // Parse '('.
      if (T.expectAndConsume(diag::err_expected_lparen_after,
                             getOpenMPClauseName(CKind).data())) {
        TPA.Revert();
        SkipUntil(tok::annot_pragma_openmp_end);
        return Directive;
      }

      OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
      if (CKind == OMPC_when) {
        // parse and get OMPTraitInfo to pass to the When clause
        parseOMPContextSelectors(Loc, TI);
        if (TI.Sets.size() == 0) {
          Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
          TPA.Commit();
          return Directive;
        }

        // Parse ':'
        if (Tok.is(tok::colon))
          ConsumeAnyToken();
        else {
          Diag(Tok, diag::err_omp_expected_colon) << "when clause";
          TPA.Commit();
          return Directive;
        }
      }

      // Skip Directive for now. We will parse directive in the second iteration
      int paren = 0;
      while (Tok.isNot(tok::r_paren) || paren != 0) {
        if (Tok.is(tok::l_paren))
          paren++;
        if (Tok.is(tok::r_paren))
          paren--;
        if (Tok.is(tok::annot_pragma_openmp_end)) {
          Diag(Tok, diag::err_omp_expected_punc)
              << getOpenMPClauseName(CKind) << 0;
          TPA.Commit();
          return Directive;
        }
        ConsumeAnyToken();
      }
      // Parse ')'
      if (Tok.is(tok::r_paren))
        T.consumeClose();

      VariantMatchInfo VMI;
      TI.getAsVariantMatchInfo(ASTContext, VMI);

      VMIs.push_back(VMI);
    }

    TPA.Revert();
    // End of the first iteration. Parser is reset to the start of metadirective

    std::function<void(StringRef)> DiagUnknownTrait =
        [this, Loc](StringRef ISATrait) {
          // TODO Track the selector locations in a way that is accessible here
          // to improve the diagnostic location.
          Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
        };
    TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
                            /* CurrentFunctionDecl */ nullptr,
                            ArrayRef<llvm::omp::TraitProperty>(),
                            Actions.OpenMP().getOpenMPDeviceNum());

    // A single match is returned for OpenMP 5.0
    int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);

    int Idx = 0;
    // In OpenMP 5.0 metadirective is either replaced by another directive or
    // ignored.
    // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
    // found by getBestWhenMatchForContext.
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
      // OpenMP 5.0 implementation - Skip to the best index found.
      if (Idx++ != BestIdx) {
        ConsumeToken();  // Consume clause name
        T.consumeOpen(); // Consume '('
        int paren = 0;
        // Skip everything inside the clause
        while (Tok.isNot(tok::r_paren) || paren != 0) {
          if (Tok.is(tok::l_paren))
            paren++;
          if (Tok.is(tok::r_paren))
            paren--;
          ConsumeAnyToken();
        }
        // Parse ')'
        if (Tok.is(tok::r_paren))
          T.consumeClose();
        continue;
      }

      OpenMPClauseKind CKind = Tok.isAnnotation()
                                   ? OMPC_unknown
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
      SourceLocation Loc = ConsumeToken();

      // Parse '('.
      T.consumeOpen();

      // Skip ContextSelectors for when clause
      if (CKind == OMPC_when) {
        OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
        // parse and skip the ContextSelectors
        parseOMPContextSelectors(Loc, TI);

        // Parse ':'
        ConsumeAnyToken();
      }

      // If no directive is passed, skip in OpenMP 5.0.
      // TODO: Generate nothing directive from OpenMP 5.1.
      if (Tok.is(tok::r_paren)) {
        SkipUntil(tok::annot_pragma_openmp_end);
        break;
      }

      // Parse Directive
      Directive = ParseOpenMPDeclarativeOrExecutableDirective(
          StmtCtx,
          /*ReadDirectiveWithinMetadirective=*/true);
      break;
    }
    // If no match is found and no otherwise clause is present, skip
    // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
    // if one was specified without an associated directive variant.
    if (BestIdx == -1 && Idx == 1) {
      assert(Tok.is(tok::annot_pragma_openmp_end) &&
             "Expecting the end of the pragma here");
      ConsumeAnnotationToken();
      return StmtEmpty();
    }
    break;
  }
  case OMPD_threadprivate: {
    // FIXME: Should this be permitted in C++?
    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
        ParsedStmtContext()) {
      Diag(Tok, diag::err_omp_immediate_directive)
          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
    }
    ConsumeToken();
    DeclDirectiveListParserHelper Helper(this, DKind);
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
                                  /*AllowScopeSpecifier=*/false)) {
      skipUntilPragmaOpenMPEnd(DKind);
      DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
          Loc, Helper.getIdentifiers());
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    }
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  }
  case OMPD_allocate: {
    // FIXME: Should this be permitted in C++?
    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
        ParsedStmtContext()) {
      Diag(Tok, diag::err_omp_immediate_directive)
          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
    }
    ConsumeToken();
    DeclDirectiveListParserHelper Helper(this, DKind);
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
                                  /*AllowScopeSpecifier=*/false)) {
      SmallVector<OMPClause *, 1> Clauses;
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
        llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
        while (Tok.isNot(tok::annot_pragma_openmp_end)) {
          OpenMPClauseKind CKind =
              Tok.isAnnotation() ? OMPC_unknown
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
          Actions.OpenMP().StartOpenMPClause(CKind);
          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
                                                !SeenClauses[unsigned(CKind)]);
          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
                    StopBeforeMatch);
          SeenClauses[unsigned(CKind)] = true;
          if (Clause != nullptr)
            Clauses.push_back(Clause);
          if (Tok.is(tok::annot_pragma_openmp_end)) {
            Actions.OpenMP().EndOpenMPClause();
            break;
          }
          // Skip ',' if any.
          if (Tok.is(tok::comma))
            ConsumeToken();
          Actions.OpenMP().EndOpenMPClause();
        }
        skipUntilPragmaOpenMPEnd(DKind);
      }
      DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
          Loc, Helper.getIdentifiers(), Clauses);
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    }
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  }
  case OMPD_declare_reduction:
    ConsumeToken();
    if (DeclGroupPtrTy Res =
            ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
      skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
      ConsumeAnyToken();
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    } else {
      SkipUntil(tok::annot_pragma_openmp_end);
    }
    break;
  case OMPD_declare_mapper: {
    ConsumeToken();
    if (DeclGroupPtrTy Res =
            ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
      // Skip the last annot_pragma_openmp_end.
      ConsumeAnnotationToken();
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    } else {
      SkipUntil(tok::annot_pragma_openmp_end);
    }
    break;
  }
  case OMPD_declare_target: {
    SourceLocation DTLoc = ConsumeAnyToken();
    bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
    SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
    if (HasClauses)
      ParseOMPDeclareTargetClauses(DTCI);
    bool HasImplicitMappings =
        !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);

    if (HasImplicitMappings) {
      Diag(Tok, diag::err_omp_unexpected_directive)
          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
      SkipUntil(tok::annot_pragma_openmp_end);
      break;
    }

    // Skip the last annot_pragma_openmp_end.
    ConsumeAnyToken();

    Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
    break;
  }
  case OMPD_begin_declare_variant: {
    ConsumeToken();
    if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {
      // Skip the last annot_pragma_openmp_end.
      if (!isEofOrEom())
        ConsumeAnnotationToken();
    }
    return Directive;
  }
  case OMPD_end_declare_variant: {
    ConsumeToken();
    if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
      Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
    else
      Diag(Loc, diag::err_expected_begin_declare_variant);
    ConsumeAnnotationToken();
    break;
  }
  case OMPD_declare_simd:
  case OMPD_begin_declare_target:
  case OMPD_end_declare_target:
  case OMPD_requires:
  case OMPD_declare_variant:
    Diag(Tok, diag::err_omp_unexpected_directive)
        << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  case OMPD_assume: {
    ConsumeToken();
    Directive = ParseOpenMPInformationalDirective(
        StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
    assert(!Directive.isUnset() &&
           "Informational directive remains unprocessed");
    return Directive;
  }
  case OMPD_unknown:
  default:
    Diag(Tok, diag::err_omp_unknown_directive);
    SkipUntil(tok::annot_pragma_openmp_end);
    break;
  }
  return Directive;
}

bool Parser::ParseOpenMPSimpleVarList(
    OpenMPDirectiveKind Kind,
    const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
        &Callback,
    bool AllowScopeSpecifier) {
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPDirectiveName(Kind, OMPVersion).data()))
    return true;
  bool IsCorrect = true;
  bool NoIdentIsFound = true;

  // Read tokens while ')' or annot_pragma_openmp_end is not found.
  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
    CXXScopeSpec SS;
    UnqualifiedId Name;
    // Read var name.
    Token PrevTok = Tok;
    NoIdentIsFound = false;

    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
        ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
                                       /*ObjectHasErrors=*/false, false)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
                                  /*ObjectHadErrors=*/false, false, false,
                                  false, false, nullptr, Name)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
               Tok.isNot(tok::annot_pragma_openmp_end)) {
      IsCorrect = false;
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
      Diag(PrevTok.getLocation(), diag::err_expected)
          << tok::identifier
          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
    } else {
      Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
    }
    // Consume ','.
    if (Tok.is(tok::comma)) {
      ConsumeToken();
    }
  }

  if (NoIdentIsFound) {
    Diag(Tok, diag::err_expected) << tok::identifier;
    IsCorrect = false;
  }

  // Parse ')'.
  IsCorrect = !T.consumeClose() && IsCorrect;

  return !IsCorrect;
}

OMPClause *Parser::ParseOpenMPSizesClause() {
  SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
  SmallVector<Expr *, 4> ValExprs;
  if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
                                ValExprs))
    return nullptr;

  return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
                                                 OpenLoc, CloseLoc);
}

OMPClause *Parser::ParseOpenMPPermutationClause() {
  SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
  SmallVector<Expr *> ArgExprs;
  if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,
                                CloseLoc, ArgExprs,
                                /*ReqIntConst=*/true))
    return nullptr;

  return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,
                                                       OpenLoc, CloseLoc);
}

OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
  SourceLocation Loc = Tok.getLocation();
  ConsumeAnyToken();

  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
    return nullptr;
  SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
  do {
    CXXScopeSpec SS;
    Token Replacement;
    ExprResult Allocator =
        getLangOpts().CPlusPlus
            ? ParseCXXIdExpression()
            : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
                                      Replacement);
    if (Allocator.isInvalid()) {
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
      break;
    }
    SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
    D.Allocator = Allocator.get();
    if (Tok.is(tok::l_paren)) {
      BalancedDelimiterTracker T(*this, tok::l_paren,
                                 tok::annot_pragma_openmp_end);
      T.consumeOpen();
      ExprResult AllocatorTraits =
          getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
      T.consumeClose();
      if (AllocatorTraits.isInvalid()) {
        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                  StopBeforeMatch);
        break;
      }
      D.AllocatorTraits = AllocatorTraits.get();
      D.LParenLoc = T.getOpenLocation();
      D.RParenLoc = T.getCloseLocation();
    }
    if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
      Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
    // Parse ','
    if (Tok.is(tok::comma))
      ConsumeAnyToken();
  } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
  T.consumeClose();
  return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
      Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
}

OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                     OpenMPClauseKind CKind, bool FirstClause) {
  OMPClauseKind = CKind;
  OMPClause *Clause = nullptr;
  bool ErrorFound = false;
  bool WrongDirective = false;
  unsigned OMPVersion = Actions.getLangOpts().OpenMP;

  // Check if clause is allowed for the given directive.
  if (CKind != OMPC_unknown &&
      !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
    Diag(Tok, diag::err_omp_unexpected_clause)
        << getOpenMPClauseName(CKind)
        << getOpenMPDirectiveName(DKind, OMPVersion);
    ErrorFound = true;
    WrongDirective = true;
  }

  switch (CKind) {
  case OMPC_final:
  case OMPC_num_threads:
  case OMPC_safelen:
  case OMPC_simdlen:
  case OMPC_collapse:
  case OMPC_ordered:
  case OMPC_priority:
  case OMPC_grainsize:
  case OMPC_num_tasks:
  case OMPC_hint:
  case OMPC_allocator:
  case OMPC_depobj:
  case OMPC_detach:
  case OMPC_novariants:
  case OMPC_nocontext:
  case OMPC_filter:
  case OMPC_partial:
  case OMPC_align:
  case OMPC_message:
  case OMPC_ompx_dyn_cgroup_mem:
    // OpenMP [2.5, Restrictions]
    //  At most one num_threads clause can appear on the directive.
    // OpenMP [2.8.1, simd construct, Restrictions]
    //  Only one safelen  clause can appear on a simd directive.
    //  Only one simdlen  clause can appear on a simd directive.
    //  Only one collapse clause can appear on a simd directive.
    // OpenMP [2.11.1, task Construct, Restrictions]
    //  At most one if clause can appear on the directive.
    //  At most one final clause can appear on the directive.
    // OpenMP [teams Construct, Restrictions]
    //  At most one num_teams clause can appear on the directive.
    //  At most one thread_limit clause can appear on the directive.
    // OpenMP [2.9.1, task Construct, Restrictions]
    // At most one priority clause can appear on the directive.
    // OpenMP [2.9.2, taskloop Construct, Restrictions]
    // At most one grainsize clause can appear on the directive.
    // OpenMP [2.9.2, taskloop Construct, Restrictions]
    // At most one num_tasks clause can appear on the directive.
    // OpenMP [2.11.3, allocate Directive, Restrictions]
    // At most one allocator clause can appear on the directive.
    // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
    // At most one detach clause can appear on the directive.
    // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
    // At most one novariants clause can appear on a dispatch directive.
    // At most one nocontext clause can appear on a dispatch directive.
    // OpenMP [5.1, error directive, Restrictions]
    // At most one message clause can appear on the directive
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }

    if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
        PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
      Clause = ParseOpenMPClause(CKind, WrongDirective);
    else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
             CKind == OMPC_num_threads)
      Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
    else
      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
    break;
  case OMPC_fail:
  case OMPC_default:
  case OMPC_proc_bind:
  case OMPC_atomic_default_mem_order:
  case OMPC_at:
  case OMPC_severity:
  case OMPC_bind:
    // OpenMP [2.14.3.1, Restrictions]
    //  Only a single default clause may be specified on a parallel, task or
    //  teams directive.
    // OpenMP [2.5, parallel Construct, Restrictions]
    //  At most one proc_bind clause can appear on the directive.
    // OpenMP [5.0, Requires directive, Restrictions]
    //  At most one atomic_default_mem_order clause can appear
    //  on the directive
    // OpenMP [5.1, error directive, Restrictions]
    //  At most one at clause can appear on the directive
    //  At most one severity clause can appear on the directive
    // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
    // At most one bind clause can appear on a loop directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }

    Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
    break;
  case OMPC_device:
  case OMPC_schedule:
  case OMPC_dist_schedule:
  case OMPC_defaultmap:
  case OMPC_order:
    // OpenMP [2.7.1, Restrictions, p. 3]
    //  Only one schedule clause can appear on a loop directive.
    // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
    //  At most one defaultmap clause can appear on the directive.
    // OpenMP 5.0 [2.12.5, target construct, Restrictions]
    //  At most one device clause can appear on the directive.
    // OpenMP 5.1 [2.11.3, order clause, Restrictions]
    //  At most one order clause may appear on a construct.
    if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
        (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }
    [[fallthrough]];
  case OMPC_if:
    Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
    break;
  case OMPC_holds:
    Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
    break;
  case OMPC_nowait:
  case OMPC_untied:
  case OMPC_mergeable:
  case OMPC_read:
  case OMPC_write:
  case OMPC_capture:
  case OMPC_compare:
  case OMPC_seq_cst:
  case OMPC_acq_rel:
  case OMPC_acquire:
  case OMPC_release:
  case OMPC_relaxed:
  case OMPC_weak:
  case OMPC_threads:
  case OMPC_simd:
  case OMPC_nogroup:
  case OMPC_unified_address:
  case OMPC_unified_shared_memory:
  case OMPC_reverse_offload:
  case OMPC_dynamic_allocators:
  case OMPC_full:
    // OpenMP [2.7.1, Restrictions, p. 9]
    //  Only one ordered clause can appear on a loop directive.
    // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
    //  Only one nowait clause can appear on a for directive.
    // OpenMP [5.0, Requires directive, Restrictions]
    //   Each of the requires clauses can appear at most once on the directive.
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }

    Clause = ParseOpenMPClause(CKind, WrongDirective);
    break;
  case OMPC_self_maps:
    // OpenMP [6.0, self_maps clause]
    if (getLangOpts().OpenMP < 60) {
      Diag(Tok, diag::err_omp_expected_clause)
          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
      ErrorFound = true;
    }
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }
    Clause = ParseOpenMPClause(CKind, WrongDirective);
    break;
  case OMPC_update:
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }

    Clause = (DKind == OMPD_depobj)
                 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
                 : ParseOpenMPClause(CKind, WrongDirective);
    break;
  case OMPC_num_teams:
  case OMPC_thread_limit:
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }
    [[fallthrough]];
  case OMPC_private:
  case OMPC_firstprivate:
  case OMPC_lastprivate:
  case OMPC_shared:
  case OMPC_reduction:
  case OMPC_task_reduction:
  case OMPC_in_reduction:
  case OMPC_linear:
  case OMPC_aligned:
  case OMPC_copyin:
  case OMPC_copyprivate:
  case OMPC_flush:
  case OMPC_depend:
  case OMPC_map:
  case OMPC_to:
  case OMPC_from:
  case OMPC_use_device_ptr:
  case OMPC_use_device_addr:
  case OMPC_is_device_ptr:
  case OMPC_has_device_addr:
  case OMPC_allocate:
  case OMPC_nontemporal:
  case OMPC_inclusive:
  case OMPC_exclusive:
  case OMPC_affinity:
  case OMPC_doacross:
  case OMPC_enter:
    if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
        CKind == OMPC_depend)
      Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
    Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
    break;
  case OMPC_sizes:
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }

    Clause = ParseOpenMPSizesClause();
    break;
  case OMPC_permutation:
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }
    Clause = ParseOpenMPPermutationClause();
    break;
  case OMPC_uses_allocators:
    Clause = ParseOpenMPUsesAllocatorClause(DKind);
    break;
  case OMPC_destroy:
    if (DKind != OMPD_interop) {
      if (!FirstClause) {
        Diag(Tok, diag::err_omp_more_one_clause)
            << getOpenMPDirectiveName(DKind, OMPVersion)
            << getOpenMPClauseName(CKind) << 0;
        ErrorFound = true;
      }
      Clause = ParseOpenMPClause(CKind, WrongDirective);
      break;
    }
    [[fallthrough]];
  case OMPC_init:
  case OMPC_use:
    Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
    break;
  case OMPC_device_type:
  case OMPC_unknown:
    skipUntilPragmaOpenMPEnd(DKind);
    break;
  case OMPC_threadprivate:
  case OMPC_uniform:
  case OMPC_match:
    if (!WrongDirective)
      Diag(Tok, diag::err_omp_unexpected_clause)
          << getOpenMPClauseName(CKind)
          << getOpenMPDirectiveName(DKind, OMPVersion);
    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
    break;
  case OMPC_absent:
  case OMPC_contains: {
    SourceLocation Loc = ConsumeToken();
    SourceLocation LLoc = Tok.getLocation();
    SourceLocation RLoc;
    llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();
    do {
      OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
      if (DK == OMPD_unknown) {
        skipUntilPragmaOpenMPEnd(OMPD_assume);
        Diag(Tok, diag::err_omp_unexpected_clause)
            << getOpenMPClauseName(CKind)
            << getOpenMPDirectiveName(DKind, OMPVersion);
        break;
      }
      if (isOpenMPExecutableDirective(DK)) {
        DKVec.push_back(DK);
        ConsumeToken();
      } else {
        Diag(Tok, diag::err_omp_unexpected_clause)
            << getOpenMPClauseName(CKind)
            << getOpenMPDirectiveName(DKind, OMPVersion);
      }
    } while (TryConsumeToken(tok::comma));
    RLoc = Tok.getLocation();
    T.consumeClose();
    Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
        CKind, DKVec, Loc, LLoc, RLoc);
    break;
  }
  case OMPC_no_openmp:
  case OMPC_no_openmp_routines:
  case OMPC_no_openmp_constructs:
  case OMPC_no_parallelism: {
    if (!FirstClause) {
      Diag(Tok, diag::err_omp_more_one_clause)
          << getOpenMPDirectiveName(DKind, OMPVersion)
          << getOpenMPClauseName(CKind) << 0;
      ErrorFound = true;
    }
    SourceLocation Loc = ConsumeToken();
    Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
        CKind, Loc, Tok.getLocation());
    break;
  }
  case OMPC_ompx_attribute:
    Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
    break;
  case OMPC_ompx_bare:
    if (DKind == llvm::omp::Directive::OMPD_target) {
      // Flang splits the combined directives which requires OMPD_target to be
      // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
      // to explicitly check whether this clause is applied to an `omp target`
      // without `teams` and emit an error.
      Diag(Tok, diag::err_omp_unexpected_clause)
          << getOpenMPClauseName(CKind)
          << getOpenMPDirectiveName(DKind, OMPVersion);
      ErrorFound = true;
      WrongDirective = true;
    }
    if (WrongDirective)
      Diag(Tok, diag::note_ompx_bare_clause)
          << getOpenMPClauseName(CKind) << "target teams";
    if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
      Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
          << getOpenMPClauseName(CKind)
          << getOpenMPDirectiveName(DKind, OMPVersion);
      ErrorFound = true;
    }
    Clause = ParseOpenMPClause(CKind, WrongDirective);
    break;
  default:
    break;
  }
  return ErrorFound ? nullptr : Clause;
}

/// Parses simple expression in parens for single-expression clauses of OpenMP
/// constructs.
/// \param RLoc Returned location of right paren.
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
                                         SourceLocation &RLoc,
                                         bool IsAddressOfOperand) {
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
    return ExprError();

  SourceLocation ELoc = Tok.getLocation();
  ExprResult LHS(
      ParseCastExpression(CastParseKind::AnyCastExpr, IsAddressOfOperand,
                          TypoCorrectionTypeBehavior::AllowNonTypes));
  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);

  // Parse ')'.
  RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();

  return Val;
}

OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                               bool ParseOnly) {
  SourceLocation Loc = ConsumeToken();
  SourceLocation LLoc = Tok.getLocation();
  SourceLocation RLoc;

  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);

  if (Val.isInvalid())
    return nullptr;

  if (ParseOnly)
    return nullptr;
  return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
                                                      LLoc, RLoc);
}

bool Parser::ParseOpenMPIndirectClause(
    SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
  SourceLocation Loc = ConsumeToken();
  SourceLocation RLoc;

  if (Tok.isNot(tok::l_paren)) {
    if (ParseOnly)
      return false;
    DTCI.Indirect = nullptr;
    return true;
  }

  ExprResult Val =
      ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
  if (Val.isInvalid())
    return false;

  if (ParseOnly)
    return false;

  if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
      !Val.get()->isInstantiationDependent() &&
      !Val.get()->containsUnexpandedParameterPack()) {
    ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
    if (Ret.isInvalid())
      return false;
    llvm::APSInt Result;
    Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
                                                  AllowFoldKind::Allow);
    if (Ret.isInvalid())
      return false;
    DTCI.Indirect = Val.get();
    return true;
  }
  return false;
}

bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
                                 OpenMPClauseKind Kind) {
  const Token &Tok = getCurToken();
  bool HasError = false;
  bool IsTarget = false;
  bool IsTargetSync = false;

  while (Tok.is(tok::identifier)) {
    // Currently prefer_type is only allowed with 'init' and it must be first.
    bool PreferTypeAllowed = Kind == OMPC_init &&
                             InteropInfo.PreferTypes.empty() && !IsTarget &&
                             !IsTargetSync;
    if (Tok.getIdentifierInfo()->isStr("target")) {
      // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
      // Each interop-type may be specified on an action-clause at most
      // once.
      if (IsTarget)
        Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
      IsTarget = true;
      ConsumeToken();
    } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
      if (IsTargetSync)
        Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
      IsTargetSync = true;
      ConsumeToken();
    } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
               PreferTypeAllowed) {
      ConsumeToken();
      BalancedDelimiterTracker PT(*this, tok::l_paren,
                                  tok::annot_pragma_openmp_end);
      if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
        HasError = true;

      while (Tok.isNot(tok::r_paren)) {
        SourceLocation Loc = Tok.getLocation();
        ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
        ExprResult PTExpr = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
        PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
                                             /*DiscardedValue=*/false);
        if (PTExpr.isUsable()) {
          InteropInfo.PreferTypes.push_back(PTExpr.get());
        } else {
          HasError = true;
          SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                    StopBeforeMatch);
        }

        if (Tok.is(tok::comma))
          ConsumeToken();
      }
      PT.consumeClose();
    } else {
      HasError = true;
      Diag(Tok, diag::err_omp_expected_interop_type);
      ConsumeToken();
    }
    if (!Tok.is(tok::comma))
      break;
    ConsumeToken();
  }

  if (!HasError && !IsTarget && !IsTargetSync) {
    Diag(Tok, diag::err_omp_expected_interop_type);
    HasError = true;
  }

  if (Kind == OMPC_init) {
    if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
      Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
    if (Tok.is(tok::colon))
      ConsumeToken();
  }

  // As of OpenMP 5.1,there are two interop-types, "target" and
  // "targetsync". Either or both are allowed for a single interop.
  InteropInfo.IsTarget = IsTarget;
  InteropInfo.IsTargetSync = IsTargetSync;

  return HasError;
}

OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
                                            bool ParseOnly) {
  SourceLocation Loc = ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind).data()))
    return nullptr;

  bool InteropError = false;
  OMPInteropInfo InteropInfo;
  if (Kind == OMPC_init)
    InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);

  // Parse the variable.
  SourceLocation VarLoc = Tok.getLocation();
  ExprResult InteropVarExpr = ParseAssignmentExpression();
  if (!InteropVarExpr.isUsable()) {
    SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
              StopBeforeMatch);
  }

  // Parse ')'.
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();

  if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
    return nullptr;

  if (Kind == OMPC_init)
    return Actions.OpenMP().ActOnOpenMPInitClause(
        InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
        RLoc);
  if (Kind == OMPC_use)
    return Actions.OpenMP().ActOnOpenMPUseClause(
        InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);

  if (Kind == OMPC_destroy)
    return Actions.OpenMP().ActOnOpenMPDestroyClause(
        InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);

  llvm_unreachable("Unexpected interop variable clause.");
}

OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
  SourceLocation Loc = ConsumeToken();
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(OMPC_ompx_attribute).data()))
    return nullptr;

  ParsedAttributes ParsedAttrs(AttrFactory);
  ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);

  // Parse ')'.
  if (T.consumeClose())
    return nullptr;

  if (ParseOnly)
    return nullptr;

  SmallVector<Attr *> Attrs;
  for (const ParsedAttr &PA : ParsedAttrs) {
    switch (PA.getKind()) {
    case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
      if (!PA.checkExactlyNumArgs(Actions, 2))
        continue;
      if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
              PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
        Attrs.push_back(A);
      continue;
    case ParsedAttr::AT_AMDGPUWavesPerEU:
      if (!PA.checkAtLeastNumArgs(Actions, 1) ||
          !PA.checkAtMostNumArgs(Actions, 2))
        continue;
      if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
              PA, PA.getArgAsExpr(0),
              PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
        Attrs.push_back(A);
      continue;
    case ParsedAttr::AT_CUDALaunchBounds:
      if (!PA.checkAtLeastNumArgs(Actions, 1) ||
          !PA.checkAtMostNumArgs(Actions, 2))
        continue;
      if (auto *A = Actions.CreateLaunchBoundsAttr(
              PA, PA.getArgAsExpr(0),
              PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
              PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
        Attrs.push_back(A);
      continue;
    default:
      Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
      continue;
    };
  }

  return Actions.OpenMP().ActOnOpenMPXAttributeClause(
      Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
}

OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
                                           bool ParseOnly) {
  std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
  if (!Val || ParseOnly)
    return nullptr;
  if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
      (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
       static_cast<DefaultKind>(Val->Type) ==
           OMP_DEFAULT_firstprivate)) {
    Diag(Val->LOpen, diag::err_omp_invalid_dsa)
        << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
                                       OMP_DEFAULT_private
                                   ? OMPC_private
                                   : OMPC_firstprivate)
        << getOpenMPClauseName(OMPC_default) << "5.1";
    return nullptr;
  }
  return Actions.OpenMP().ActOnOpenMPSimpleClause(
      Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
}

OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
  SourceLocation Loc = Tok.getLocation();
  ConsumeAnyToken();

  if (ParseOnly)
    return nullptr;
  return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
}

OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
                                                      OpenMPClauseKind Kind,
                                                      bool ParseOnly) {
  SourceLocation Loc = ConsumeToken();
  SourceLocation DelimLoc;
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind).data()))
    return nullptr;

  ExprResult Val;
  SmallVector<unsigned, 4> Arg;
  SmallVector<SourceLocation, 4> KLoc;
  if (Kind == OMPC_schedule) {
    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
    Arg.resize(NumberOfElements);
    KLoc.resize(NumberOfElements);
    Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
    Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
    Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
    unsigned KindModifier = getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
    if (KindModifier > OMPC_SCHEDULE_unknown) {
      // Parse 'modifier'
      Arg[Modifier1] = KindModifier;
      KLoc[Modifier1] = Tok.getLocation();
      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
          Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeAnyToken();
      if (Tok.is(tok::comma)) {
        // Parse ',' 'modifier'
        ConsumeAnyToken();
        KindModifier = getOpenMPSimpleClauseType(
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
        Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
                             ? KindModifier
                             : (unsigned)OMPC_SCHEDULE_unknown;
        KLoc[Modifier2] = Tok.getLocation();
        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
            Tok.isNot(tok::annot_pragma_openmp_end))
          ConsumeAnyToken();
      }
      // Parse ':'
      if (Tok.is(tok::colon))
        ConsumeAnyToken();
      else
        Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
      KindModifier = getOpenMPSimpleClauseType(
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
    }
    Arg[ScheduleKind] = KindModifier;
    KLoc[ScheduleKind] = Tok.getLocation();
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
         Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
         Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
        Tok.is(tok::comma))
      DelimLoc = ConsumeAnyToken();
  } else if (Kind == OMPC_dist_schedule) {
    Arg.push_back(getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
      DelimLoc = ConsumeAnyToken();
  } else if (Kind == OMPC_defaultmap) {
    // Get a defaultmap modifier
    unsigned Modifier = getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

    // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
    // pointer
    if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
      Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
    Arg.push_back(Modifier);
    KLoc.push_back(Tok.getLocation());
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
    // Parse ':'
    if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
      if (Tok.is(tok::colon))
        ConsumeAnyToken();
      else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
        Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
      // Get a defaultmap kind
      Arg.push_back(getOpenMPSimpleClauseType(
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
      KLoc.push_back(Tok.getLocation());
      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
          Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeAnyToken();
    } else {
      Arg.push_back(OMPC_DEFAULTMAP_unknown);
      KLoc.push_back(SourceLocation());
    }
  } else if (Kind == OMPC_order) {
    enum { Modifier, OrderKind, NumberOfElements };
    Arg.resize(NumberOfElements);
    KLoc.resize(NumberOfElements);
    Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
    Arg[OrderKind] = OMPC_ORDER_unknown;
    unsigned KindModifier = getOpenMPSimpleClauseType(
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
    if (KindModifier > OMPC_ORDER_unknown) {
      // Parse 'modifier'
      Arg[Modifier] = KindModifier;
      KLoc[Modifier] = Tok.getLocation();
      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
          Tok.isNot(tok::annot_pragma_openmp_end))
        ConsumeAnyToken();
      // Parse ':'
      if (Tok.is(tok::colon))
        ConsumeAnyToken();
      else
        Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
      KindModifier = getOpenMPSimpleClauseType(
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
    }
    Arg[OrderKind] = KindModifier;
    KLoc[OrderKind] = Tok.getLocation();
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
        Tok.isNot(tok::annot_pragma_openmp_end))
      ConsumeAnyToken();
  } else if (Kind == OMPC_device) {
    // Only target executable directives support extended device construct.
    if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
        NextToken().is(tok::colon)) {
      // Parse optional <device modifier> ':'
      Arg.push_back(getOpenMPSimpleClauseType(
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
      KLoc.push_back(Tok.getLocation());
      ConsumeAnyToken();
      // Parse ':'
      ConsumeAnyToken();
    } else {
      Arg.push_back(OMPC_DEVICE_unknown);
      KLoc.emplace_back();
    }
  } else if (Kind == OMPC_grainsize) {
    // Parse optional <grainsize modifier> ':'
    OpenMPGrainsizeClauseModifier Modifier =
        static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
            getLangOpts()));
    if (getLangOpts().OpenMP >= 51) {
      if (NextToken().is(tok::colon)) {
        Arg.push_back(Modifier);
        KLoc.push_back(Tok.getLocation());
        // Parse modifier
        ConsumeAnyToken();
        // Parse ':'
        ConsumeAnyToken();
      } else {
        if (Modifier == OMPC_GRAINSIZE_strict) {
          Diag(Tok, diag::err_modifier_expected_colon) << "strict";
          // Parse modifier
          ConsumeAnyToken();
        }
        Arg.push_back(OMPC_GRAINSIZE_unknown);
        KLoc.emplace_back();
      }
    } else {
      Arg.push_back(OMPC_GRAINSIZE_unknown);
      KLoc.emplace_back();
    }
  } else if (Kind == OMPC_num_tasks) {
    // Parse optional <num_tasks modifier> ':'
    OpenMPNumTasksClauseModifier Modifier =
        static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
            getLangOpts()));
    if (getLangOpts().OpenMP >= 51) {
      if (NextToken().is(tok::colon)) {
        Arg.push_back(Modifier);
        KLoc.push_back(Tok.getLocation());
        // Parse modifier
        ConsumeAnyToken();
        // Parse ':'
        ConsumeAnyToken();
      } else {
        if (Modifier == OMPC_NUMTASKS_strict) {
          Diag(Tok, diag::err_modifier_expected_colon) << "strict";
          // Parse modifier
          ConsumeAnyToken();
        }
        Arg.push_back(OMPC_NUMTASKS_unknown);
        KLoc.emplace_back();
      }
    } else {
      Arg.push_back(OMPC_NUMTASKS_unknown);
      KLoc.emplace_back();
    }
  } else if (Kind == OMPC_num_threads) {
    // Parse optional <num_threads modifier> ':'
    OpenMPNumThreadsClauseModifier Modifier =
        static_cast<OpenMPNumThreadsClauseModifier>(getOpenMPSimpleClauseType(
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
            getLangOpts()));
    if (getLangOpts().OpenMP >= 60) {
      if (NextToken().is(tok::colon)) {
        Arg.push_back(Modifier);
        KLoc.push_back(Tok.getLocation());
        // Parse modifier
        ConsumeAnyToken();
        // Parse ':'
        ConsumeAnyToken();
      } else {
        if (Modifier == OMPC_NUMTHREADS_strict) {
          Diag(Tok, diag::err_modifier_expected_colon) << "strict";
          // Parse modifier
          ConsumeAnyToken();
        }
        Arg.push_back(OMPC_NUMTHREADS_unknown);
        KLoc.emplace_back();
      }
    } else {
      Arg.push_back(OMPC_NUMTHREADS_unknown);
      KLoc.emplace_back();
    }
  } else {
    assert(Kind == OMPC_if);
    KLoc.push_back(Tok.getLocation());
    TentativeParsingAction TPA(*this);
    auto DK = parseOpenMPDirectiveKind(*this);
    Arg.push_back(static_cast<unsigned>(DK));
    if (DK != OMPD_unknown) {
      ConsumeToken();
      if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
        TPA.Commit();
        DelimLoc = ConsumeToken();
      } else {
        TPA.Revert();
        Arg.back() = unsigned(OMPD_unknown);
      }
    } else {
      TPA.Revert();
    }
  }

  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
                          (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
                          Kind == OMPC_if || Kind == OMPC_device ||
                          Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
                          Kind == OMPC_num_threads;
  if (NeedAnExpression) {
    SourceLocation ELoc = Tok.getLocation();
    ExprResult LHS(
        ParseCastExpression(CastParseKind::AnyCastExpr, false,
                            TypoCorrectionTypeBehavior::AllowNonTypes));
    Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
    Val =
        Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
  }

  // Parse ')'.
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();

  if (NeedAnExpression && Val.isInvalid())
    return nullptr;

  if (ParseOnly)
    return nullptr;
  return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
}

static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
                             UnqualifiedId &ReductionId) {
  if (ReductionIdScopeSpec.isEmpty()) {
    auto OOK = OO_None;
    switch (P.getCurToken().getKind()) {
    case tok::plus:
      OOK = OO_Plus;
      break;
    case tok::minus:
      OOK = OO_Minus;
      break;
    case tok::star:
      OOK = OO_Star;
      break;
    case tok::amp:
      OOK = OO_Amp;
      break;
    case tok::pipe:
      OOK = OO_Pipe;
      break;
    case tok::caret:
      OOK = OO_Caret;
      break;
    case tok::ampamp:
      OOK = OO_AmpAmp;
      break;
    case tok::pipepipe:
      OOK = OO_PipePipe;
      break;
    default:
      break;
    }
    if (OOK != OO_None) {
      SourceLocation OpLoc = P.ConsumeToken();
      SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
      return false;
    }
  }
  return P.ParseUnqualifiedId(
      ReductionIdScopeSpec, /*ObjectType=*/nullptr,
      /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
      /*AllowDestructorName*/ false,
      /*AllowConstructorName*/ false,
      /*AllowDeductionGuide*/ false, nullptr, ReductionId);
}

/// Checks if the token is a valid map-type-modifier.
/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
static OpenMPMapModifierKind isMapModifier(Parser &P) {
  Token Tok = P.getCurToken();
  if (!Tok.is(tok::identifier))
    return OMPC_MAP_MODIFIER_unknown;

  Preprocessor &PP = P.getPreprocessor();
  OpenMPMapModifierKind TypeModifier =
      static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
          OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
  return TypeModifier;
}

bool Parser::parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data) {
  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
  if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
              StopBeforeMatch);
    return true;
  }
  // Parse mapper-identifier
  if (getLangOpts().CPlusPlus)
    ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
                                   /*ObjectType=*/nullptr,
                                   /*ObjectHasErrors=*/false,
                                   /*EnteringContext=*/false);
  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
    Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
              StopBeforeMatch);
    return true;
  }
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
  Data.ReductionOrMapperId = DeclarationNameInfo(
      DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
  ConsumeToken();
  // Parse ')'.
  return T.consumeClose();
}

static OpenMPMapClauseKind isMapType(Parser &P);

bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) {
  bool HasMapType = false;
  SourceLocation PreMapLoc = Tok.getLocation();
  StringRef PreMapName = "";
  while (getCurToken().isNot(tok::colon)) {
    OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
    OpenMPMapClauseKind MapKind = isMapType(*this);
    if (TypeModifier == OMPC_MAP_MODIFIER_always ||
        TypeModifier == OMPC_MAP_MODIFIER_close ||
        TypeModifier == OMPC_MAP_MODIFIER_present ||
        TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
      Data.MapTypeModifiers.push_back(TypeModifier);
      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
      if (PP.LookAhead(0).isNot(tok::comma) &&
          PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
        Diag(Tok.getLocation(), diag::err_omp_missing_comma)
            << "map type modifier";
      ConsumeToken();
    } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
      Data.MapTypeModifiers.push_back(TypeModifier);
      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
      ConsumeToken();
      if (parseMapperModifier(Data))
        return true;
      if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
          getLangOpts().OpenMP >= 52)
        Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
            << "map type modifier";

    } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
      if (!HasMapType) {
        HasMapType = true;
        Data.ExtraModifier = MapKind;
        MapKind = OMPC_MAP_unknown;
        PreMapLoc = Tok.getLocation();
        PreMapName = Tok.getIdentifierInfo()->getName();
      } else {
        Diag(Tok, diag::err_omp_more_one_map_type);
        Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
            << PreMapName;
      }
      ConsumeToken();
    } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
      Data.MapTypeModifiers.push_back(TypeModifier);
      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
      if (PP.LookAhead(0).isNot(tok::comma) &&
          PP.LookAhead(0).isNot(tok::colon))
        Diag(Tok.getLocation(), diag::err_omp_missing_comma)
            << "map type modifier";
      if (getLangOpts().OpenMP < 60)
        Diag(Tok, diag::err_omp_unknown_map_type_modifier)
            << (getLangOpts().OpenMP >= 51
                    ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
                    : 0)
            << getLangOpts().OpenMPExtensions << 0;
      ConsumeToken();
    } else {
      // For the case of unknown map-type-modifier or a map-type.
      // Map-type is followed by a colon; the function returns when it
      // encounters a token followed by a colon.
      if (Tok.is(tok::comma)) {
        Diag(Tok, diag::err_omp_map_type_modifier_missing);
        ConsumeToken();
        continue;
      }
      // Potential map-type token as it is followed by a colon.
      if (PP.LookAhead(0).is(tok::colon)) {
        if (getLangOpts().OpenMP >= 60) {
          break;
        } else {
          return false;
        }
      }

      Diag(Tok, diag::err_omp_unknown_map_type_modifier)
          << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
                                         : 0)
          << getLangOpts().OpenMPExtensions
          << (getLangOpts().OpenMP >= 60 ? 1 : 0);
      ConsumeToken();
    }
    if (getCurToken().is(tok::comma))
      ConsumeToken();
  }
  if (getLangOpts().OpenMP >= 60 && !HasMapType) {
    if (!Tok.is(tok::colon)) {
      Diag(Tok, diag::err_omp_unknown_map_type);
      ConsumeToken();
    } else {
      Data.ExtraModifier = OMPC_MAP_unknown;
    }
  }
  return false;
}

/// Checks if the token is a valid map-type.
/// If it is not MapType kind, OMPC_MAP_unknown is returned.
static OpenMPMapClauseKind isMapType(Parser &P) {
  Token Tok = P.getCurToken();
  // The map-type token can be either an identifier or the C++ delete keyword.
  if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
    return OMPC_MAP_unknown;
  Preprocessor &PP = P.getPreprocessor();
  unsigned MapType =
      getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts());
  if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
      MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
      MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
    return static_cast<OpenMPMapClauseKind>(MapType);
  return OMPC_MAP_unknown;
}

/// Parse map-type in map clause.
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
/// where, map-type ::= to | from | tofrom | alloc | release | delete
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data) {
  Token Tok = P.getCurToken();
  if (Tok.is(tok::colon)) {
    P.Diag(Tok, diag::err_omp_map_type_missing);
    return;
  }
  Data.ExtraModifier = isMapType(P);
  if (Data.ExtraModifier == OMPC_MAP_unknown)
    P.Diag(Tok, diag::err_omp_unknown_map_type);
  P.ConsumeToken();
}

ExprResult Parser::ParseOpenMPIteratorsExpr() {
  assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
         "Expected 'iterator' token.");
  SourceLocation IteratorKwLoc = ConsumeToken();

  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
    return ExprError();

  SourceLocation LLoc = T.getOpenLocation();
  SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
    // Check if the type parsing is required.
    ParsedType IteratorType;
    if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
      // identifier '=' is not found - parse type.
      TypeResult TR = ParseTypeName();
      if (TR.isInvalid()) {
        T.skipToEnd();
        return ExprError();
      }
      IteratorType = TR.get();
    }

    // Parse identifier.
    IdentifierInfo *II = nullptr;
    SourceLocation IdLoc;
    if (Tok.is(tok::identifier)) {
      II = Tok.getIdentifierInfo();
      IdLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::err_expected_unqualified_id) << 0;
    }

    // Parse '='.
    SourceLocation AssignLoc;
    if (Tok.is(tok::equal))
      AssignLoc = ConsumeToken();
    else
      Diag(Tok, diag::err_omp_expected_equal_in_iterator);

    // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
    ColonProtectionRAIIObject ColonRAII(*this);
    // Parse <begin>
    SourceLocation Loc = Tok.getLocation();
    ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
    ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
    Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
                                        /*DiscardedValue=*/false);
    // Parse ':'.
    SourceLocation ColonLoc;
    if (Tok.is(tok::colon))
      ColonLoc = ConsumeToken();

    // Parse <end>
    Loc = Tok.getLocation();
    LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
    ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
    End = Actions.ActOnFinishFullExpr(End.get(), Loc,
                                      /*DiscardedValue=*/false);

    SourceLocation SecColonLoc;
    ExprResult Step;
    // Parse optional step.
    if (Tok.is(tok::colon)) {
      // Parse ':'
      SecColonLoc = ConsumeToken();
      // Parse <step>
      Loc = Tok.getLocation();
      LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
      Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
      Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
                                         /*DiscardedValue=*/false);
    }

    // Parse ',' or ')'
    if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
      Diag(Tok, diag::err_omp_expected_punc_after_iterator);
    if (Tok.is(tok::comma))
      ConsumeToken();

    SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
    D.DeclIdent = II;
    D.DeclIdentLoc = IdLoc;
    D.Type = IteratorType;
    D.AssignLoc = AssignLoc;
    D.ColonLoc = ColonLoc;
    D.SecColonLoc = SecColonLoc;
    D.Range.Begin = Begin.get();
    D.Range.End = End.get();
    D.Range.Step = Step.get();
  }

  // Parse ')'.
  SourceLocation RLoc = Tok.getLocation();
  if (!T.consumeClose())
    RLoc = T.getCloseLocation();

  return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
                                               LLoc, RLoc, Data);
}

bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,
                                        SemaOpenMP::OpenMPVarListDataTy &Data,
                                        const LangOptions &LangOpts) {
  // Currently the only reserved locator is 'omp_all_memory' which is only
  // allowed on a depend clause.
  if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
    return false;

  if (Tok.is(tok::identifier) &&
      Tok.getIdentifierInfo()->isStr("omp_all_memory")) {

    if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
        Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
      Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
    else if (Data.ExtraModifier != OMPC_DEPEND_out &&
             Data.ExtraModifier != OMPC_DEPEND_inout)
      Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
    else
      Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
                               ? OMPC_DEPEND_outallmemory
                               : OMPC_DEPEND_inoutallmemory;
    ConsumeToken();
    return true;
  }
  return false;
}

/// Parse step size expression. Returns true if parsing is successfull,
/// otherwise returns false.
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data,
                          OpenMPClauseKind CKind, SourceLocation ELoc) {
  ExprResult Tail = P.ParseAssignmentExpression();
  Sema &Actions = P.getActions();
  Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
                                     /*DiscardedValue*/ false);
  if (Tail.isUsable()) {
    Data.DepModOrTailExpr = Tail.get();
    Token CurTok = P.getCurToken();
    if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
      P.Diag(CurTok, diag::err_expected_punc) << "step expression";
    }
    return true;
  }
  return false;
}

/// Parse 'allocate' clause modifiers.
///   If allocator-modifier exists, return an expression for it. For both
///   allocator and align modifiers, set Data fields as appropriate.
static ExprResult
parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind,
                                   SemaOpenMP::OpenMPVarListDataTy &Data) {
  const Token &Tok = P.getCurToken();
  Preprocessor &PP = P.getPreprocessor();
  ExprResult Tail;
  ExprResult Val;
  SourceLocation RLoc;
  bool AllocatorSeen = false;
  bool AlignSeen = false;
  SourceLocation CurrentModifierLoc = Tok.getLocation();
  auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
      getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));

  // Modifiers did not exist before 5.1
  if (P.getLangOpts().OpenMP < 51)
    return P.ParseAssignmentExpression();

  // An allocator-simple-modifier is exclusive and must appear alone. See
  // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
  // description of "exclusive" property. If we don't recognized an explicit
  // simple-/complex- modifier, assume we're looking at expression
  // representing allocator and consider ourselves done.
  if (CurrentModifier == OMPC_ALLOCATE_unknown)
    return P.ParseAssignmentExpression();

  do {
    P.ConsumeToken();
    if (Tok.is(tok::l_paren)) {
      switch (CurrentModifier) {
      case OMPC_ALLOCATE_allocator: {
        if (AllocatorSeen) {
          P.Diag(Tok, diag::err_omp_duplicate_modifier)
              << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
              << getOpenMPClauseName(Kind);
        } else {
          Data.AllocClauseModifiers.push_back(CurrentModifier);
          Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
        }
        BalancedDelimiterTracker AllocateT(P, tok::l_paren,
                                           tok::annot_pragma_openmp_end);
        AllocateT.consumeOpen();
        Tail = P.ParseAssignmentExpression();
        AllocateT.consumeClose();
        AllocatorSeen = true;
        break;
      }
      case OMPC_ALLOCATE_align: {
        if (AlignSeen) {
          P.Diag(Tok, diag::err_omp_duplicate_modifier)
              << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
              << getOpenMPClauseName(Kind);
        } else {
          Data.AllocClauseModifiers.push_back(CurrentModifier);
          Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
        }
        Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
        if (Val.isUsable())
          Data.AllocateAlignment = Val.get();
        AlignSeen = true;
        break;
      }
      default:
        llvm_unreachable("Unexpected allocate modifier");
      }
    } else {
      P.Diag(Tok, diag::err_expected) << tok::l_paren;
    }
    if (Tok.isNot(tok::comma))
      break;
    P.ConsumeToken();
    CurrentModifierLoc = Tok.getLocation();
    CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
        getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));
    // A modifier followed by a comma implies another modifier.
    if (CurrentModifier == OMPC_ALLOCATE_unknown) {
      P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
      break;
    }
  } while (!AllocatorSeen || !AlignSeen);
  return Tail;
}

bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
                                OpenMPClauseKind Kind,
                                SmallVectorImpl<Expr *> &Vars,
                                SemaOpenMP::OpenMPVarListDataTy &Data) {
  UnqualifiedId UnqualifiedReductionId;
  bool InvalidReductionId = false;
  bool IsInvalidMapperModifier = false;

  // Parse '('.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                         getOpenMPClauseName(Kind).data()))
    return true;

  bool HasIterator = false;
  bool InvalidIterator = false;
  bool NeedRParenForLinear = false;
  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
                                   tok::annot_pragma_openmp_end);
  // Handle reduction-identifier for reduction clause.
  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
      Kind == OMPC_in_reduction) {
    Data.ExtraModifier = OMPC_REDUCTION_unknown;
    if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
        (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
        NextToken().is(tok::comma)) {
      // Parse optional reduction modifier.
      Data.ExtraModifier =
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
      Data.ExtraModifierLoc = Tok.getLocation();
      ConsumeToken();
      assert(Tok.is(tok::comma) && "Expected comma.");
      (void)ConsumeToken();
    }
    // Handle original(private / shared) Modifier
    if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
        Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
        NextToken().is(tok::l_paren)) {
      // Parse original(private) modifier.
      ConsumeToken();
      BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
      ParenT.consumeOpen();
      if (Tok.is(tok::kw_private)) {
        Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
        Data.OriginalSharingModifierLoc = Tok.getLocation();
        ConsumeToken();
      } else if (Tok.is(tok::identifier) &&
                 (PP.getSpelling(Tok) == "shared" ||
                  PP.getSpelling(Tok) == "default")) {
        Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
        Data.OriginalSharingModifierLoc = Tok.getLocation();
        ConsumeToken();
      } else {
        Diag(Tok.getLocation(), diag::err_expected)
            << "'private or shared or default'";
        SkipUntil(tok::r_paren);
        return false;
      }
      ParenT.consumeClose();
      if (!Tok.is(tok::comma)) {
        Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
        return false;
      }
      (void)ConsumeToken();
    }
    ColonProtectionRAIIObject ColonRAII(*this);
    if (getLangOpts().CPlusPlus)
      ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
                                     /*ObjectType=*/nullptr,
                                     /*ObjectHasErrors=*/false,
                                     /*EnteringContext=*/false);
    InvalidReductionId = ParseReductionId(
        *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
    if (InvalidReductionId) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
    else
      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
    if (!InvalidReductionId)
      Data.ReductionOrMapperId =
          Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
  } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
    if (getLangOpts().OpenMP >= 50) {
      if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
        // Handle optional dependence modifier.
        // iterator(iterators-definition)
        // where iterators-definition is iterator-specifier [,
        // iterators-definition ]
        // where iterator-specifier is [ iterator-type ] identifier =
        // range-specification
        HasIterator = true;
        EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
        ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
        Data.DepModOrTailExpr = IteratorRes.get();
        // Parse ','
        ExpectAndConsume(tok::comma);
      }
    }
    // Handle dependency type for depend clause.
    ColonProtectionRAIIObject ColonRAII(*this);
    Data.ExtraModifier = getOpenMPSimpleClauseType(
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
        getLangOpts());
    Data.ExtraModifierLoc = Tok.getLocation();
    if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
        (Kind == OMPC_doacross &&
         Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    } else {
      ConsumeToken();
      // Special processing for depend(source) clause.
      if (DKind == OMPD_ordered && Kind == OMPC_depend &&
          Data.ExtraModifier == OMPC_DEPEND_source) {
        // Parse ')'.
        T.consumeClose();
        return false;
      }
    }
    if (Tok.is(tok::colon)) {
      Data.ColonLoc = ConsumeToken();
    } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
      Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
                                      : diag::warn_pragma_expected_colon)
          << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
    }
    if (Kind == OMPC_doacross) {
      if (Tok.is(tok::identifier) &&
          Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
        Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
                                 ? OMPC_DOACROSS_source_omp_cur_iteration
                                 : OMPC_DOACROSS_sink_omp_cur_iteration;
        ConsumeToken();
      }
      if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
        if (Tok.isNot(tok::minus)) {
          Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
              << getOpenMPClauseName(Kind) << 0 << 0;
          SkipUntil(tok::r_paren);
          return false;
        } else {
          ConsumeToken();
          SourceLocation Loc = Tok.getLocation();
          uint64_t Value = 0;
          if (Tok.isNot(tok::numeric_constant) ||
              (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
            Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
                << getOpenMPClauseName(Kind) << 0 << 0;
            SkipUntil(tok::r_paren);
            return false;
          }
        }
      }
      if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
        if (Tok.isNot(tok::r_paren)) {
          Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
              << getOpenMPClauseName(Kind) << 1 << 1;
          SkipUntil(tok::r_paren);
          return false;
        }
      }
      // Only the 'sink' case has the expression list.
      if (Kind == OMPC_doacross &&
          (Data.ExtraModifier == OMPC_DOACROSS_source ||
           Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
           Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
        // Parse ')'.
        T.consumeClose();
        return false;
      }
    }
  } else if (Kind == OMPC_linear) {
    // Try to parse modifier if any.
    Data.ExtraModifier = OMPC_LINEAR_val;
    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
      Data.ExtraModifier =
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
      Data.ExtraModifierLoc = ConsumeToken();
      LinearT.consumeOpen();
      NeedRParenForLinear = true;
      if (getLangOpts().OpenMP >= 52)
        Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
            << "linear-modifier(list)" << getOpenMPClauseName(Kind)
            << "linear(list: [linear-modifier,] step(step-size))";
    }
  } else if (Kind == OMPC_lastprivate) {
    // Try to parse modifier if any.
    Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
    // Conditional modifier allowed only in OpenMP 5.0 and not supported in
    // distribute and taskloop based directives.
    if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
         !isOpenMPTaskLoopDirective(DKind)) &&
        Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
      Data.ExtraModifier =
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
      Data.ExtraModifierLoc = Tok.getLocation();
      ConsumeToken();
      assert(Tok.is(tok::colon) && "Expected colon.");
      Data.ColonLoc = ConsumeToken();
    }
  } else if (Kind == OMPC_map) {
    // Handle optional iterator map modifier.
    if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
      HasIterator = true;
      EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
      Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
      ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
      Data.IteratorExpr = IteratorRes.get();
      // Parse ','
      ExpectAndConsume(tok::comma);
      if (getLangOpts().OpenMP < 52) {
        Diag(Tok, diag::err_omp_unknown_map_type_modifier)
            << (getLangOpts().OpenMP >= 51 ? 1 : 0)
            << getLangOpts().OpenMPExtensions << 0;
        InvalidIterator = true;
      }
    }
    // Handle map type for map clause.
    ColonProtectionRAIIObject ColonRAII(*this);

    // The first identifier may be a list item, a map-type or a
    // map-type-modifier. The map-type can also be delete which has the same
    // spelling of the C++ delete keyword.
    Data.ExtraModifier = OMPC_MAP_unknown;
    Data.ExtraModifierLoc = Tok.getLocation();

    // Check for presence of a colon in the map clause.
    TentativeParsingAction TPA(*this);
    bool ColonPresent = false;
    if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                  StopBeforeMatch)) {
      if (Tok.is(tok::colon))
        ColonPresent = true;
    }
    TPA.Revert();
    // Only parse map-type-modifier[s] and map-type if a colon is present in
    // the map clause.
    if (ColonPresent) {
      if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
        Diag(Tok, diag::err_omp_map_modifier_specification_list);
      IsInvalidMapperModifier = parseMapTypeModifiers(Data);
      if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
        parseMapType(*this, Data);
      else
        SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
    }
    if (Data.ExtraModifier == OMPC_MAP_unknown) {
      Data.ExtraModifier = OMPC_MAP_tofrom;
      if (getLangOpts().OpenMP >= 52) {
        if (DKind == OMPD_target_enter_data)
          Data.ExtraModifier = OMPC_MAP_to;
        else if (DKind == OMPD_target_exit_data)
          Data.ExtraModifier = OMPC_MAP_from;
      }
      Data.IsMapTypeImplicit = true;
    }

    if (Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
  } else if (Kind == OMPC_to || Kind == OMPC_from) {
    while (Tok.is(tok::identifier)) {
      auto Modifier = static_cast<OpenMPMotionModifierKind>(
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
      if (Modifier == OMPC_MOTION_MODIFIER_unknown)
        break;
      Data.MotionModifiers.push_back(Modifier);
      Data.MotionModifiersLoc.push_back(Tok.getLocation());
      ConsumeToken();
      if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
        IsInvalidMapperModifier = parseMapperModifier(Data);
        if (IsInvalidMapperModifier)
          break;
      }
      // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
      if (getLangOpts().OpenMP < 51)
        break;
      // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
      // TODO: Is that intentional?
      if (Tok.is(tok::comma))
        ConsumeToken();
    }
    if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
      if (!IsInvalidMapperModifier) {
        if (getLangOpts().OpenMP < 51)
          Diag(Tok, diag::warn_pragma_expected_colon) << ")";
        else
          Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
      }
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
    // OpenMP 5.1 permits a ':' even without a preceding modifier.  TODO: Is
    // that intentional?
    if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
        Tok.is(tok::colon))
      Data.ColonLoc = ConsumeToken();
  } else if (Kind == OMPC_allocate ||
             (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
              PP.getSpelling(Tok) == "iterator")) {
    // Handle optional allocator and align modifiers followed by colon
    // delimiter.
    ColonProtectionRAIIObject ColonRAII(*this);
    TentativeParsingAction TPA(*this);
    // OpenMP 5.0, 2.10.1, task Construct.
    // where aff-modifier is one of the following:
    // iterator(iterators-definition)
    ExprResult Tail;
    if (Kind == OMPC_allocate) {
      Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
    } else {
      HasIterator = true;
      EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
      Tail = ParseOpenMPIteratorsExpr();
    }
    Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
                                       /*DiscardedValue=*/false);
    if (Tail.isUsable() || Data.AllocateAlignment) {
      if (Tok.is(tok::colon)) {
        Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
        Data.ColonLoc = ConsumeToken();
        TPA.Commit();
      } else {
        // Colon not found, parse only list of variables.
        TPA.Revert();
        if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
          SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
                    StopBeforeMatch);
          Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
        }
      }
    } else {
      // Parsing was unsuccessfull, revert and skip to the end of clause or
      // directive.
      TPA.Revert();
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                StopBeforeMatch);
    }
  } else if (Kind == OMPC_adjust_args) {
    // Handle adjust-op for adjust_args clause.
    ColonProtectionRAIIObject ColonRAII(*this);
    Data.ExtraModifier = getOpenMPSimpleClauseType(
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
        getLangOpts());
    Data.ExtraModifierLoc = Tok.getLocation();
    if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
      Diag(Tok, diag::err_omp_unknown_adjust_args_op)
          << (getLangOpts().OpenMP >= 60 ? 1 : 0);
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
    } else {
      ConsumeToken();
      if (Tok.is(tok::colon))
        Data.ColonLoc = Tok.getLocation();
      ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
                       "adjust-op");
    }
  }

  bool IsComma =
      (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
       Kind != OMPC_in_reduction && Kind != OMPC_depend &&
       Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
      (Kind == OMPC_reduction && !InvalidReductionId) ||
      (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
      (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
      (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
      (Kind == OMPC_adjust_args &&
       Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
                     Tok.isNot(tok::annot_pragma_openmp_end))) {
    ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
    if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {
      // Parse variable
      ExprResult VarExpr = ParseAssignmentExpression();
      if (VarExpr.isUsable()) {
        Vars.push_back(VarExpr.get());
      } else {
        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                  StopBeforeMatch);
      }
    }
    // Skip ',' if any
    IsComma = Tok.is(tok::comma);
    if (IsComma)
      ConsumeToken();
    else if (Tok.isNot(tok::r_paren) &&
             Tok.isNot(tok::annot_pragma_openmp_end) &&
             (!MayHaveTail || Tok.isNot(tok::colon))) {
      unsigned OMPVersion = Actions.getLangOpts().OpenMP;
      Diag(Tok, diag::err_omp_expected_punc)
          << ((Kind == OMPC_flush)
                  ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
                  : getOpenMPClauseName(Kind))
          << (Kind == OMPC_flush);
    }
  }

  // Parse ')' for linear clause with modifier.
  if (NeedRParenForLinear)
    LinearT.consumeClose();
  // Parse ':' linear modifiers (val, uval, ref or step(step-size))
  // or parse ':' alignment.
  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
  bool StepFound = false;
  bool ModifierFound = false;
  if (MustHaveTail) {
    Data.ColonLoc = Tok.getLocation();
    SourceLocation ELoc = ConsumeToken();

    if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
      bool Malformed = false;
      while (Tok.isNot(tok::r_paren)) {
        if (Tok.is(tok::identifier)) {
          // identifier could be a linear kind (val, uval, ref) or step
          // modifier or step size
          OpenMPLinearClauseKind LinKind =
              static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType(
                  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
                  getLangOpts()));

          if (LinKind == OMPC_LINEAR_step) {
            if (StepFound)
              Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;

            BalancedDelimiterTracker StepT(*this, tok::l_paren,
                                           tok::annot_pragma_openmp_end);
            SourceLocation StepModifierLoc = ConsumeToken();
            // parse '('
            if (StepT.consumeOpen())
              Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";

            // parse step size expression
            StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
            if (StepFound)
              Data.StepModifierLoc = StepModifierLoc;

            // parse ')'
            StepT.consumeClose();
          } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
            if (ModifierFound)
              Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;

            Data.ExtraModifier = LinKind;
            Data.ExtraModifierLoc = ConsumeToken();
            ModifierFound = true;
          } else {
            StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
            if (!StepFound) {
              Malformed = true;
              SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                        StopBeforeMatch);
            }
          }
        } else {
          // parse an integer expression as step size
          StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
        }

        if (Tok.is(tok::comma))
          ConsumeToken();
        if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
          break;
      }
      if (!Malformed && !StepFound && !ModifierFound)
        Diag(ELoc, diag::err_expected_expression);
    } else {
      // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
      ExprResult Tail = ParseAssignmentExpression();
      Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
                                         /*DiscardedValue*/ false);
      if (Tail.isUsable())
        Data.DepModOrTailExpr = Tail.get();
      else
        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
                  StopBeforeMatch);
    }
  }

  // Parse ')'.
  Data.RLoc = Tok.getLocation();
  if (!T.consumeClose())
    Data.RLoc = T.getCloseLocation();
  // Exit from scope when the iterator is used in depend clause.
  if (HasIterator)
    ExitScope();
  return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
          Vars.empty()) ||
         (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
         InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
}

OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
                                            OpenMPClauseKind Kind,
                                            bool ParseOnly) {
  SourceLocation Loc = Tok.getLocation();
  SourceLocation LOpen = ConsumeToken();
  SmallVector<Expr *, 4> Vars;
  SemaOpenMP::OpenMPVarListDataTy Data;

  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
    return nullptr;

  if (ParseOnly)
    return nullptr;
  OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
  return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
}

bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
                                       SourceLocation &ClauseNameLoc,
                                       SourceLocation &OpenLoc,
                                       SourceLocation &CloseLoc,
                                       SmallVectorImpl<Expr *> &Exprs,
                                       bool ReqIntConst) {
  assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
         "Expected parsing to start at clause name");
  ClauseNameLoc = ConsumeToken();

  // Parse inside of '(' and ')'.
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
  if (T.consumeOpen()) {
    Diag(Tok, diag::err_expected) << tok::l_paren;
    return true;
  }

  // Parse the list with interleaved commas.
  do {
    ExprResult Val =
        ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression();
    if (!Val.isUsable()) {
      // Encountered something other than an expression; abort to ')'.
      T.skipToEnd();
      return true;
    }
    Exprs.push_back(Val.get());
  } while (TryConsumeToken(tok::comma));

  bool Result = T.consumeClose();
  OpenLoc = T.getOpenLocation();
  CloseLoc = T.getCloseLocation();
  return Result;
}
