brintos

brintos / llvm-project-archived public Read only

0
0
Text · 191.2 KiB · 15c3f75 Raw
5244 lines · cpp
1//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file implements parsing of all OpenMP directives and clauses.10///11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/OpenMPClause.h"15#include "clang/Basic/DiagnosticParse.h"16#include "clang/Basic/OpenMPKinds.h"17#include "clang/Basic/TargetInfo.h"18#include "clang/Basic/TokenKinds.h"19#include "clang/Parse/Parser.h"20#include "clang/Parse/RAIIObjectsForParser.h"21#include "clang/Sema/EnterExpressionEvaluationContext.h"22#include "clang/Sema/Scope.h"23#include "clang/Sema/SemaAMDGPU.h"24#include "clang/Sema/SemaCodeCompletion.h"25#include "clang/Sema/SemaOpenMP.h"26#include "llvm/ADT/SmallBitVector.h"27#include "llvm/ADT/StringSwitch.h"28#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"29#include "llvm/Frontend/OpenMP/OMPAssume.h"30#include "llvm/Frontend/OpenMP/OMPContext.h"31#include <optional>32 33using namespace clang;34using namespace llvm::omp;35 36//===----------------------------------------------------------------------===//37// OpenMP declarative directives.38//===----------------------------------------------------------------------===//39 40namespace {41class DeclDirectiveListParserHelper final {42  SmallVector<Expr *, 4> Identifiers;43  Parser *P;44  OpenMPDirectiveKind Kind;45 46public:47  DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)48      : P(P), Kind(Kind) {}49  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {50    ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(51        P->getCurScope(), SS, NameInfo, Kind);52    if (Res.isUsable())53      Identifiers.push_back(Res.get());54  }55  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }56};57} // namespace58 59static OpenMPDirectiveKind checkOpenMPDirectiveName(Parser &P,60                                                    SourceLocation Loc,61                                                    OpenMPDirectiveKind Kind,62                                                    StringRef Name) {63  unsigned Version = P.getLangOpts().OpenMP;64  auto [D, VR] = getOpenMPDirectiveKindAndVersions(Name);65  assert(D == Kind && "Directive kind mismatch");66  // Ignore the case Version > VR.Max: In OpenMP 6.0 all prior spellings67  // are explicitly allowed.68  if (static_cast<int>(Version) < VR.Min)69    P.Diag(Loc, diag::warn_omp_future_directive_spelling) << Name;70 71  return Kind;72}73 74static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {75  static const DirectiveNameParser DirParser;76 77  const DirectiveNameParser::State *S = DirParser.initial();78 79  Token Tok = P.getCurToken();80  if (Tok.isAnnotation())81    return OMPD_unknown;82 83  std::string Concat = P.getPreprocessor().getSpelling(Tok);84  SourceLocation Loc = Tok.getLocation();85 86  S = DirParser.consume(S, Concat);87  if (S == nullptr)88    return OMPD_unknown;89 90  while (!Tok.isAnnotation()) {91    OpenMPDirectiveKind DKind = S->Value;92    Tok = P.getPreprocessor().LookAhead(0);93    if (!Tok.isAnnotation()) {94      std::string TS = P.getPreprocessor().getSpelling(Tok);95      S = DirParser.consume(S, TS);96      if (S == nullptr)97        return checkOpenMPDirectiveName(P, Loc, DKind, Concat);98      Concat += ' ' + TS;99      P.ConsumeToken();100    }101  }102 103  assert(S && "Should have exited early");104  return checkOpenMPDirectiveName(P, Loc, S->Value, Concat);105}106 107static DeclarationName parseOpenMPReductionId(Parser &P) {108  Token Tok = P.getCurToken();109  Sema &Actions = P.getActions();110  OverloadedOperatorKind OOK = OO_None;111  // Allow to use 'operator' keyword for C++ operators112  bool WithOperator = false;113  if (Tok.is(tok::kw_operator)) {114    P.ConsumeToken();115    Tok = P.getCurToken();116    WithOperator = true;117  }118  switch (Tok.getKind()) {119  case tok::plus: // '+'120    OOK = OO_Plus;121    break;122  case tok::minus: // '-'123    OOK = OO_Minus;124    break;125  case tok::star: // '*'126    OOK = OO_Star;127    break;128  case tok::amp: // '&'129    OOK = OO_Amp;130    break;131  case tok::pipe: // '|'132    OOK = OO_Pipe;133    break;134  case tok::caret: // '^'135    OOK = OO_Caret;136    break;137  case tok::ampamp: // '&&'138    OOK = OO_AmpAmp;139    break;140  case tok::pipepipe: // '||'141    OOK = OO_PipePipe;142    break;143  case tok::identifier: // identifier144    if (!WithOperator)145      break;146    [[fallthrough]];147  default:148    P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);149    P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,150                Parser::StopBeforeMatch);151    return DeclarationName();152  }153  P.ConsumeToken();154  auto &DeclNames = Actions.getASTContext().DeclarationNames;155  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())156                        : DeclNames.getCXXOperatorName(OOK);157}158 159Parser::DeclGroupPtrTy160Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {161  unsigned OMPVersion = Actions.getLangOpts().OpenMP;162  // Parse '('.163  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);164  if (T.expectAndConsume(165          diag::err_expected_lparen_after,166          getOpenMPDirectiveName(OMPD_declare_reduction, OMPVersion).data())) {167    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);168    return DeclGroupPtrTy();169  }170 171  DeclarationName Name = parseOpenMPReductionId(*this);172  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))173    return DeclGroupPtrTy();174 175  // Consume ':'.176  bool IsCorrect = !ExpectAndConsume(tok::colon);177 178  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))179    return DeclGroupPtrTy();180 181  IsCorrect = IsCorrect && !Name.isEmpty();182 183  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {184    Diag(Tok.getLocation(), diag::err_expected_type);185    IsCorrect = false;186  }187 188  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))189    return DeclGroupPtrTy();190 191  SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;192  // Parse list of types until ':' token.193  do {194    ColonProtectionRAIIObject ColonRAII(*this);195    SourceRange Range;196    TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS);197    if (TR.isUsable()) {198      QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(199          Range.getBegin(), TR);200      if (!ReductionType.isNull()) {201        ReductionTypes.push_back(202            std::make_pair(ReductionType, Range.getBegin()));203      }204    } else {205      SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,206                StopBeforeMatch);207    }208 209    if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))210      break;211 212    // Consume ','.213    if (ExpectAndConsume(tok::comma)) {214      IsCorrect = false;215      if (Tok.is(tok::annot_pragma_openmp_end)) {216        Diag(Tok.getLocation(), diag::err_expected_type);217        return DeclGroupPtrTy();218      }219    }220  } while (Tok.isNot(tok::annot_pragma_openmp_end));221 222  if (ReductionTypes.empty()) {223    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);224    return DeclGroupPtrTy();225  }226 227  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))228    return DeclGroupPtrTy();229 230  // Consume ':'.231  if (ExpectAndConsume(tok::colon))232    IsCorrect = false;233 234  if (Tok.is(tok::annot_pragma_openmp_end)) {235    Diag(Tok.getLocation(), diag::err_expected_expression);236    return DeclGroupPtrTy();237  }238 239  DeclGroupPtrTy DRD =240      Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveStart(241          getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,242          AS);243 244  // Parse <combiner> expression and then parse initializer if any for each245  // correct type.246  unsigned I = 0, E = ReductionTypes.size();247  for (Decl *D : DRD.get()) {248    TentativeParsingAction TPA(*this);249    ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |250                                    Scope::CompoundStmtScope |251                                    Scope::OpenMPDirectiveScope);252    // Parse <combiner> expression.253    Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);254    ExprResult CombinerResult = Actions.ActOnFinishFullExpr(255        ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);256    Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerEnd(257        D, CombinerResult.get());258 259    if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&260        Tok.isNot(tok::annot_pragma_openmp_end)) {261      TPA.Commit();262      IsCorrect = false;263      break;264    }265    IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();266    ExprResult InitializerResult;267    if (Tok.isNot(tok::annot_pragma_openmp_end)) {268      // Parse <initializer> expression.269      if (Tok.is(tok::identifier) &&270          Tok.getIdentifierInfo()->isStr("initializer")) {271        ConsumeToken();272      } else {273        Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";274        TPA.Commit();275        IsCorrect = false;276        break;277      }278      // Parse '('.279      BalancedDelimiterTracker T(*this, tok::l_paren,280                                 tok::annot_pragma_openmp_end);281      IsCorrect =282          !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&283          IsCorrect;284      if (Tok.isNot(tok::annot_pragma_openmp_end)) {285        ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |286                                        Scope::CompoundStmtScope |287                                        Scope::OpenMPDirectiveScope);288        // Parse expression.289        VarDecl *OmpPrivParm =290            Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart(291                getCurScope(), D);292        // Check if initializer is omp_priv <init_expr> or something else.293        if (Tok.is(tok::identifier) &&294            Tok.getIdentifierInfo()->isStr("omp_priv")) {295          ConsumeToken();296          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);297        } else {298          InitializerResult = Actions.ActOnFinishFullExpr(299              ParseAssignmentExpression().get(), D->getLocation(),300              /*DiscardedValue*/ false);301        }302        Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerEnd(303            D, InitializerResult.get(), OmpPrivParm);304        if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&305            Tok.isNot(tok::annot_pragma_openmp_end)) {306          TPA.Commit();307          IsCorrect = false;308          break;309        }310        IsCorrect =311            !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();312      }313    }314 315    ++I;316    // Revert parsing if not the last type, otherwise accept it, we're done with317    // parsing.318    if (I != E)319      TPA.Revert();320    else321      TPA.Commit();322  }323  return Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveEnd(324      getCurScope(), DRD, IsCorrect);325}326 327void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {328  // Parse declarator '=' initializer.329  // If a '==' or '+=' is found, suggest a fixit to '='.330  if (isTokenEqualOrEqualTypo()) {331    ConsumeToken();332 333    if (Tok.is(tok::code_completion)) {334      cutOffParsing();335      Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),336                                                       OmpPrivParm);337      Actions.FinalizeDeclaration(OmpPrivParm);338      return;339    }340 341    PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);342    ExprResult Init = ParseInitializer(OmpPrivParm);343 344    if (Init.isInvalid()) {345      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);346      Actions.ActOnInitializerError(OmpPrivParm);347    } else {348      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),349                                   /*DirectInit=*/false);350    }351  } else if (Tok.is(tok::l_paren)) {352    // Parse C++ direct initializer: '(' expression-list ')'353    BalancedDelimiterTracker T(*this, tok::l_paren);354    T.consumeOpen();355 356    ExprVector Exprs;357 358    SourceLocation LParLoc = T.getOpenLocation();359    auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {360      QualType PreferredType =361          Actions.CodeCompletion().ProduceConstructorSignatureHelp(362              OmpPrivParm->getType()->getCanonicalTypeInternal(),363              OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);364      CalledSignatureHelp = true;365      return PreferredType;366    };367    if (ParseExpressionList(Exprs, [&] {368          PreferredType.enterFunctionArgument(Tok.getLocation(),369                                              RunSignatureHelp);370        })) {371      if (PP.isCodeCompletionReached() && !CalledSignatureHelp)372        RunSignatureHelp();373      Actions.ActOnInitializerError(OmpPrivParm);374      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);375    } else {376      // Match the ')'.377      SourceLocation RLoc = Tok.getLocation();378      if (!T.consumeClose())379        RLoc = T.getCloseLocation();380 381      ExprResult Initializer =382          Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);383      Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),384                                   /*DirectInit=*/true);385    }386  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {387    // Parse C++0x braced-init-list.388    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);389 390    ExprResult Init(ParseBraceInitializer());391 392    if (Init.isInvalid()) {393      Actions.ActOnInitializerError(OmpPrivParm);394    } else {395      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),396                                   /*DirectInit=*/true);397    }398  } else {399    Actions.ActOnUninitializedDecl(OmpPrivParm);400  }401}402 403Parser::DeclGroupPtrTy404Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {405  bool IsCorrect = true;406  unsigned OMPVersion = Actions.getLangOpts().OpenMP;407  // Parse '('408  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);409  if (T.expectAndConsume(410          diag::err_expected_lparen_after,411          getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion).data())) {412    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);413    return DeclGroupPtrTy();414  }415 416  // Parse <mapper-identifier>417  auto &DeclNames = Actions.getASTContext().DeclarationNames;418  DeclarationName MapperId;419  if (PP.LookAhead(0).is(tok::colon)) {420    if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {421      Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);422      IsCorrect = false;423    } else {424      MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());425    }426    ConsumeToken();427    // Consume ':'.428    ExpectAndConsume(tok::colon);429  } else {430    // If no mapper identifier is provided, its name is "default" by default431    MapperId =432        DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));433  }434 435  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))436    return DeclGroupPtrTy();437 438  // Parse <type> <var>439  DeclarationName VName;440  QualType MapperType;441  SourceRange Range;442  TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);443  if (ParsedType.isUsable())444    MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),445                                                               ParsedType);446  if (MapperType.isNull())447    IsCorrect = false;448  if (!IsCorrect) {449    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);450    return DeclGroupPtrTy();451  }452 453  // Consume ')'.454  IsCorrect &= !T.consumeClose();455  if (!IsCorrect) {456    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);457    return DeclGroupPtrTy();458  }459 460  Scope *OuterScope = getCurScope();461  // Enter scope.462  DeclarationNameInfo DirName;463  SourceLocation Loc = Tok.getLocation();464  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |465                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;466  ParseScope OMPDirectiveScope(this, ScopeFlags);467  Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,468                                       getCurScope(), Loc);469 470  // Add the mapper variable declaration.471  ExprResult MapperVarRef =472      Actions.OpenMP().ActOnOpenMPDeclareMapperDirectiveVarDecl(473          getCurScope(), MapperType, Range.getBegin(), VName);474 475  // Parse map clauses.476  SmallVector<OMPClause *, 6> Clauses;477  while (Tok.isNot(tok::annot_pragma_openmp_end)) {478    OpenMPClauseKind CKind = Tok.isAnnotation()479                                 ? OMPC_unknown480                                 : getOpenMPClauseKind(PP.getSpelling(Tok));481    Actions.OpenMP().StartOpenMPClause(CKind);482    OMPClause *Clause =483        ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());484    if (Clause)485      Clauses.push_back(Clause);486    else487      IsCorrect = false;488    // Skip ',' if any.489    if (Tok.is(tok::comma))490      ConsumeToken();491    Actions.OpenMP().EndOpenMPClause();492  }493  if (Clauses.empty()) {494    Diag(Tok, diag::err_omp_expected_clause)495        << getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion);496    IsCorrect = false;497  }498 499  // This needs to be called within the scope because500  // processImplicitMapsWithDefaultMappers may add clauses when analyzing nested501  // types. The scope used for calling ActOnOpenMPDeclareMapperDirective,502  // however, needs to be the outer one, otherwise declared mappers don't become503  // visible.504  DeclGroupPtrTy DG = Actions.OpenMP().ActOnOpenMPDeclareMapperDirective(505      OuterScope, Actions.getCurLexicalContext(), MapperId, MapperType,506      Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);507  // Exit scope.508  Actions.OpenMP().EndOpenMPDSABlock(nullptr);509  OMPDirectiveScope.Exit();510  if (!IsCorrect)511    return DeclGroupPtrTy();512 513  return DG;514}515 516TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,517                                                   DeclarationName &Name,518                                                   AccessSpecifier AS) {519  // Parse the common declaration-specifiers piece.520  Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;521  DeclSpec DS(AttrFactory);522  ParseSpecifierQualifierList(DS, AS, DSC);523 524  // Parse the declarator.525  DeclaratorContext Context = DeclaratorContext::Prototype;526  Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);527  ParseDeclarator(DeclaratorInfo);528  Range = DeclaratorInfo.getSourceRange();529  if (DeclaratorInfo.getIdentifier() == nullptr) {530    Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);531    return true;532  }533  Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();534 535  return Actions.OpenMP().ActOnOpenMPDeclareMapperVarDecl(getCurScope(),536                                                          DeclaratorInfo);537}538 539/// Parses 'omp begin declare variant' directive.540// The syntax is:541// { #pragma omp begin declare variant clause }542// <function-declaration-or-definition-sequence>543// { #pragma omp end declare variant }544//545bool Parser::ParseOpenMPDeclareBeginVariantDirective(SourceLocation Loc) {546  OMPTraitInfo *ParentTI =547      Actions.OpenMP().getOMPTraitInfoForSurroundingScope();548  ASTContext &ASTCtx = Actions.getASTContext();549  OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();550  if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {551    while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))552      ;553    // Skip the last annot_pragma_openmp_end.554    (void)ConsumeAnnotationToken();555    return true;556  }557 558  // Skip last tokens.559  skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);560 561  ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);562 563  VariantMatchInfo VMI;564  TI.getAsVariantMatchInfo(ASTCtx, VMI);565 566  std::function<void(StringRef)> DiagUnknownTrait = [this,567                                                     Loc](StringRef ISATrait) {568    // TODO Track the selector locations in a way that is accessible here569    // to improve the diagnostic location.570    Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;571  };572  TargetOMPContext OMPCtx(573      ASTCtx, std::move(DiagUnknownTrait),574      /* CurrentFunctionDecl */ nullptr,575      /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>(),576      Actions.OpenMP().getOpenMPDeviceNum());577 578  if (isVariantApplicableInContext(VMI, OMPCtx,579                                   /*DeviceOrImplementationSetOnly=*/true)) {580    Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);581    return false;582  }583 584  // Elide all the code till the matching end declare variant was found.585  unsigned Nesting = 1;586  SourceLocation DKLoc;587  OpenMPDirectiveKind DK = OMPD_unknown;588  do {589    DKLoc = Tok.getLocation();590    DK = parseOpenMPDirectiveKind(*this);591    if (DK == OMPD_end_declare_variant)592      --Nesting;593    else if (DK == OMPD_begin_declare_variant)594      ++Nesting;595    if (!Nesting || isEofOrEom())596      break;597    ConsumeAnyToken();598  } while (true);599 600  parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, DK,601                       Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);602  return false;603}604 605namespace {606/// RAII that recreates function context for correct parsing of clauses of607/// 'declare simd' construct.608/// OpenMP, 2.8.2 declare simd Construct609/// The expressions appearing in the clauses of this directive are evaluated in610/// the scope of the arguments of the function declaration or definition.611class FNContextRAII final {612  Parser &P;613  Sema::CXXThisScopeRAII *ThisScope;614  Parser::MultiParseScope Scopes;615  bool HasFunScope = false;616  FNContextRAII() = delete;617  FNContextRAII(const FNContextRAII &) = delete;618  FNContextRAII &operator=(const FNContextRAII &) = delete;619 620public:621  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {622    Decl *D = *Ptr.get().begin();623    NamedDecl *ND = dyn_cast<NamedDecl>(D);624    RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());625    Sema &Actions = P.getActions();626 627    // Allow 'this' within late-parsed attributes.628    ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),629                                           ND && ND->isCXXInstanceMember());630 631    // If the Decl is templatized, add template parameters to scope.632    // FIXME: Track CurTemplateDepth?633    P.ReenterTemplateScopes(Scopes, D);634 635    // If the Decl is on a function, add function parameters to the scope.636    if (D->isFunctionOrFunctionTemplate()) {637      HasFunScope = true;638      Scopes.Enter(Scope::FnScope | Scope::DeclScope |639                   Scope::CompoundStmtScope);640      Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);641    }642  }643  ~FNContextRAII() {644    if (HasFunScope)645      P.getActions().ActOnExitFunctionContext();646    delete ThisScope;647  }648};649} // namespace650 651/// Parses clauses for 'declare simd' directive.652///    clause:653///      'inbranch' | 'notinbranch'654///      'simdlen' '(' <expr> ')'655///      { 'uniform' '(' <argument_list> ')' }656///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }657///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }658static bool parseDeclareSimdClauses(659    Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,660    SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,661    SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,662    SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {663  SourceRange BSRange;664  const Token &Tok = P.getCurToken();665  bool IsError = false;666  while (Tok.isNot(tok::annot_pragma_openmp_end)) {667    if (Tok.isNot(tok::identifier))668      break;669    OMPDeclareSimdDeclAttr::BranchStateTy Out;670    IdentifierInfo *II = Tok.getIdentifierInfo();671    StringRef ClauseName = II->getName();672    // Parse 'inranch|notinbranch' clauses.673    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {674      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {675        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)676            << ClauseName677            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;678        IsError = true;679      }680      BS = Out;681      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());682      P.ConsumeToken();683    } else if (ClauseName == "simdlen") {684      if (SimdLen.isUsable()) {685        unsigned OMPVersion = P.getActions().getLangOpts().OpenMP;686        P.Diag(Tok, diag::err_omp_more_one_clause)687            << getOpenMPDirectiveName(OMPD_declare_simd, OMPVersion)688            << ClauseName << 0;689        IsError = true;690      }691      P.ConsumeToken();692      SourceLocation RLoc;693      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);694      if (SimdLen.isInvalid())695        IsError = true;696    } else {697      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);698      if (CKind == OMPC_uniform || CKind == OMPC_aligned ||699          CKind == OMPC_linear) {700        SemaOpenMP::OpenMPVarListDataTy Data;701        SmallVectorImpl<Expr *> *Vars = &Uniforms;702        if (CKind == OMPC_aligned) {703          Vars = &Aligneds;704        } else if (CKind == OMPC_linear) {705          Data.ExtraModifier = OMPC_LINEAR_val;706          Vars = &Linears;707        }708 709        P.ConsumeToken();710        if (P.ParseOpenMPVarList(OMPD_declare_simd,711                                 getOpenMPClauseKind(ClauseName), *Vars, Data))712          IsError = true;713        if (CKind == OMPC_aligned) {714          Alignments.append(Aligneds.size() - Alignments.size(),715                            Data.DepModOrTailExpr);716        } else if (CKind == OMPC_linear) {717          assert(0 <= Data.ExtraModifier &&718                 Data.ExtraModifier <= OMPC_LINEAR_unknown &&719                 "Unexpected linear modifier.");720          if (P.getActions().OpenMP().CheckOpenMPLinearModifier(721                  static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),722                  Data.ExtraModifierLoc))723            Data.ExtraModifier = OMPC_LINEAR_val;724          LinModifiers.append(Linears.size() - LinModifiers.size(),725                              Data.ExtraModifier);726          Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);727        }728      } else729        // TODO: add parsing of other clauses.730        break;731    }732    // Skip ',' if any.733    if (Tok.is(tok::comma))734      P.ConsumeToken();735  }736  return IsError;737}738 739Parser::DeclGroupPtrTy740Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,741                                   CachedTokens &Toks, SourceLocation Loc) {742  PP.EnterToken(Tok, /*IsReinject*/ true);743  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,744                      /*IsReinject*/ true);745  // Consume the previously pushed token.746  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);747  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);748 749  FNContextRAII FnContext(*this, Ptr);750  OMPDeclareSimdDeclAttr::BranchStateTy BS =751      OMPDeclareSimdDeclAttr::BS_Undefined;752  ExprResult Simdlen;753  SmallVector<Expr *, 4> Uniforms;754  SmallVector<Expr *, 4> Aligneds;755  SmallVector<Expr *, 4> Alignments;756  SmallVector<Expr *, 4> Linears;757  SmallVector<unsigned, 4> LinModifiers;758  SmallVector<Expr *, 4> Steps;759  bool IsError =760      parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,761                              Alignments, Linears, LinModifiers, Steps);762  skipUntilPragmaOpenMPEnd(OMPD_declare_simd);763  // Skip the last annot_pragma_openmp_end.764  SourceLocation EndLoc = ConsumeAnnotationToken();765  if (IsError)766    return Ptr;767  return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(768      Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,769      LinModifiers, Steps, SourceRange(Loc, EndLoc));770}771 772namespace {773/// Constant used in the diagnostics to distinguish the levels in an OpenMP774/// contexts: selector-set={selector(trait, ...), ...}, ....775enum OMPContextLvl {776  CONTEXT_SELECTOR_SET_LVL = 0,777  CONTEXT_SELECTOR_LVL = 1,778  CONTEXT_TRAIT_LVL = 2,779};780 781static StringRef stringLiteralParser(Parser &P) {782  ExprResult Res = P.ParseStringLiteralExpression(true);783  return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";784}785 786static StringRef getNameFromIdOrString(Parser &P, Token &Tok,787                                       OMPContextLvl Lvl) {788  if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {789    llvm::SmallString<16> Buffer;790    StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);791    (void)P.ConsumeToken();792    return Name;793  }794 795  if (tok::isStringLiteral(Tok.getKind()))796    return stringLiteralParser(P);797 798  P.Diag(Tok.getLocation(),799         diag::warn_omp_declare_variant_string_literal_or_identifier)800      << Lvl;801  return "";802}803 804static bool checkForDuplicates(Parser &P, StringRef Name,805                               SourceLocation NameLoc,806                               llvm::StringMap<SourceLocation> &Seen,807                               OMPContextLvl Lvl) {808  auto Res = Seen.try_emplace(Name, NameLoc);809  if (Res.second)810    return false;811 812  // Each trait-set-selector-name, trait-selector-name and trait-name can813  // only be specified once.814  P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)815      << Lvl << Name;816  P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)817      << Lvl << Name;818  return true;819}820} // namespace821 822void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,823                                       llvm::omp::TraitSet Set,824                                       llvm::omp::TraitSelector Selector,825                                       llvm::StringMap<SourceLocation> &Seen) {826  TIProperty.Kind = TraitProperty::invalid;827 828  SourceLocation NameLoc = Tok.getLocation();829  StringRef Name;830  if (Selector == llvm::omp::TraitSelector::target_device_device_num) {831    Name = "number";832    TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);833    ExprResult DeviceNumExprResult = ParseExpression();834    if (DeviceNumExprResult.isUsable()) {835      Expr *DeviceNumExpr = DeviceNumExprResult.get();836      Actions.OpenMP().ActOnOpenMPDeviceNum(DeviceNumExpr);837    }838    return;839  }840  Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);841  if (Name.empty()) {842    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)843        << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);844    return;845  }846 847  TIProperty.RawString = Name;848  TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);849  if (TIProperty.Kind != TraitProperty::invalid) {850    if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))851      TIProperty.Kind = TraitProperty::invalid;852    return;853  }854 855  // It follows diagnosis and helping notes.856  // FIXME: We should move the diagnosis string generation into libFrontend.857  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)858      << Name << getOpenMPContextTraitSelectorName(Selector)859      << getOpenMPContextTraitSetName(Set);860 861  TraitSet SetForName = getOpenMPContextTraitSetKind(Name);862  if (SetForName != TraitSet::invalid) {863    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)864        << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;865    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)866        << Name << "<selector-name>"867        << "(<property-name>)";868    return;869  }870  TraitSelector SelectorForName =871      getOpenMPContextTraitSelectorKind(Name, SetForName);872  if (SelectorForName != TraitSelector::invalid) {873    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)874        << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;875    bool AllowsTraitScore = false;876    bool RequiresProperty = false;877    isValidTraitSelectorForTraitSet(878        SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),879        AllowsTraitScore, RequiresProperty);880    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)881        << getOpenMPContextTraitSetName(882               getOpenMPContextTraitSetForSelector(SelectorForName))883        << Name << (RequiresProperty ? "(<property-name>)" : "");884    return;885  }886  for (const auto &PotentialSet :887       {TraitSet::construct, TraitSet::user, TraitSet::implementation,888        TraitSet::device, TraitSet::target_device}) {889    TraitProperty PropertyForName =890        getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);891    if (PropertyForName == TraitProperty::invalid)892      continue;893    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)894        << getOpenMPContextTraitSetName(895               getOpenMPContextTraitSetForProperty(PropertyForName))896        << getOpenMPContextTraitSelectorName(897               getOpenMPContextTraitSelectorForProperty(PropertyForName))898        << ("(" + Name + ")").str();899    return;900  }901  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)902      << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);903}904 905static bool checkExtensionProperty(Parser &P, SourceLocation Loc,906                                   OMPTraitProperty &TIProperty,907                                   OMPTraitSelector &TISelector,908                                   llvm::StringMap<SourceLocation> &Seen) {909  assert(TISelector.Kind ==910             llvm::omp::TraitSelector::implementation_extension &&911         "Only for extension properties, e.g., "912         "`implementation={extension(PROPERTY)}`");913  if (TIProperty.Kind == TraitProperty::invalid)914    return false;915 916  if (TIProperty.Kind ==917      TraitProperty::implementation_extension_disable_implicit_base)918    return true;919 920  if (TIProperty.Kind ==921      TraitProperty::implementation_extension_allow_templates)922    return true;923 924  if (TIProperty.Kind ==925      TraitProperty::implementation_extension_bind_to_declaration)926    return true;927 928  auto IsMatchExtension = [](OMPTraitProperty &TP) {929    return (TP.Kind ==930                llvm::omp::TraitProperty::implementation_extension_match_all ||931            TP.Kind ==932                llvm::omp::TraitProperty::implementation_extension_match_any ||933            TP.Kind ==934                llvm::omp::TraitProperty::implementation_extension_match_none);935  };936 937  if (IsMatchExtension(TIProperty)) {938    for (OMPTraitProperty &SeenProp : TISelector.Properties)939      if (IsMatchExtension(SeenProp)) {940        P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);941        StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(942            SeenProp.Kind, SeenProp.RawString);943        SourceLocation SeenLoc = Seen[SeenName];944        P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)945            << CONTEXT_TRAIT_LVL << SeenName;946        return false;947      }948    return true;949  }950 951  llvm_unreachable("Unknown extension property!");952}953 954void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,955                                     llvm::omp::TraitSet Set,956                                     llvm::StringMap<SourceLocation> &Seen) {957  assert(TISelector.Kind != TraitSelector::user_condition &&958         "User conditions are special properties not handled here!");959 960  SourceLocation PropertyLoc = Tok.getLocation();961  OMPTraitProperty TIProperty;962  parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);963 964  if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)965    if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,966                                TISelector, Seen))967      TIProperty.Kind = TraitProperty::invalid;968 969  // If we have an invalid property here we already issued a warning.970  if (TIProperty.Kind == TraitProperty::invalid) {971    if (PropertyLoc != Tok.getLocation())972      Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)973          << CONTEXT_TRAIT_LVL;974    return;975  }976 977  if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,978                                                 TISelector.Kind, Set)) {979 980    // If we make it here the property, selector, set, score, condition, ... are981    // all valid (or have been corrected). Thus we can record the property.982    TISelector.Properties.push_back(TIProperty);983    return;984  }985 986  Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)987      << getOpenMPContextTraitPropertyName(TIProperty.Kind,988                                           TIProperty.RawString)989      << getOpenMPContextTraitSelectorName(TISelector.Kind)990      << getOpenMPContextTraitSetName(Set);991  Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)992      << getOpenMPContextTraitPropertyName(TIProperty.Kind,993                                           TIProperty.RawString)994      << getOpenMPContextTraitSelectorName(995             getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))996      << getOpenMPContextTraitSetName(997             getOpenMPContextTraitSetForProperty(TIProperty.Kind));998  Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)999      << CONTEXT_TRAIT_LVL;1000}1001 1002void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,1003                                       llvm::omp::TraitSet Set,1004                                       llvm::StringMap<SourceLocation> &Seen) {1005  TISelector.Kind = TraitSelector::invalid;1006 1007  SourceLocation NameLoc = Tok.getLocation();1008  StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);1009  if (Name.empty()) {1010    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)1011        << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);1012    return;1013  }1014 1015  TISelector.Kind = getOpenMPContextTraitSelectorKind(Name, Set);1016  if (TISelector.Kind != TraitSelector::invalid) {1017    if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))1018      TISelector.Kind = TraitSelector::invalid;1019    return;1020  }1021 1022  // It follows diagnosis and helping notes.1023  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)1024      << Name << getOpenMPContextTraitSetName(Set);1025 1026  TraitSet SetForName = getOpenMPContextTraitSetKind(Name);1027  if (SetForName != TraitSet::invalid) {1028    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)1029        << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;1030    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)1031        << Name << "<selector-name>"1032        << "<property-name>";1033    return;1034  }1035  for (const auto &PotentialSet :1036       {TraitSet::construct, TraitSet::user, TraitSet::implementation,1037        TraitSet::device, TraitSet::target_device}) {1038    TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(1039        PotentialSet, TraitSelector::invalid, Name);1040    if (PropertyForName == TraitProperty::invalid)1041      continue;1042    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)1043        << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;1044    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)1045        << getOpenMPContextTraitSetName(1046               getOpenMPContextTraitSetForProperty(PropertyForName))1047        << getOpenMPContextTraitSelectorName(1048               getOpenMPContextTraitSelectorForProperty(PropertyForName))1049        << ("(" + Name + ")").str();1050    return;1051  }1052  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)1053      << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);1054}1055 1056/// Parse optional 'score' '(' <expr> ')' ':'.1057static ExprResult parseContextScore(Parser &P) {1058  ExprResult ScoreExpr;1059  llvm::SmallString<16> Buffer;1060  StringRef SelectorName =1061      P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);1062  if (SelectorName != "score")1063    return ScoreExpr;1064  (void)P.ConsumeToken();1065  SourceLocation RLoc;1066  ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);1067  // Parse ':'1068  if (P.getCurToken().is(tok::colon))1069    (void)P.ConsumeAnyToken();1070  else1071    P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)1072        << "':'"1073        << "score expression";1074  return ScoreExpr;1075}1076 1077void Parser::parseOMPContextSelector(1078    OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,1079    llvm::StringMap<SourceLocation> &SeenSelectors) {1080  unsigned short OuterPC = ParenCount;1081 1082  // If anything went wrong we issue an error or warning and then skip the rest1083  // of the selector. However, commas are ambiguous so we look for the nesting1084  // of parentheses here as well.1085  auto FinishSelector = [OuterPC, this]() -> void {1086    bool Done = false;1087    while (!Done) {1088      while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,1089                         tok::annot_pragma_openmp_end},1090                        StopBeforeMatch))1091        ;1092      if (Tok.is(tok::r_paren) && OuterPC > ParenCount)1093        (void)ConsumeParen();1094      if (OuterPC <= ParenCount) {1095        Done = true;1096        break;1097      }1098      if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {1099        Done = true;1100        break;1101      }1102      (void)ConsumeAnyToken();1103    }1104    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)1105        << CONTEXT_SELECTOR_LVL;1106  };1107 1108  SourceLocation SelectorLoc = Tok.getLocation();1109  parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);1110  if (TISelector.Kind == TraitSelector::invalid)1111    return FinishSelector();1112 1113  bool AllowsTraitScore = false;1114  bool RequiresProperty = false;1115  if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,1116                                       RequiresProperty)) {1117    Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)1118        << getOpenMPContextTraitSelectorName(TISelector.Kind)1119        << getOpenMPContextTraitSetName(Set);1120    Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)1121        << getOpenMPContextTraitSelectorName(TISelector.Kind)1122        << getOpenMPContextTraitSetName(1123               getOpenMPContextTraitSetForSelector(TISelector.Kind))1124        << RequiresProperty;1125    return FinishSelector();1126  }1127 1128  if (!RequiresProperty) {1129    TISelector.Properties.push_back(1130        {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),1131         getOpenMPContextTraitSelectorName(TISelector.Kind)});1132    return;1133  }1134 1135  if (!Tok.is(tok::l_paren)) {1136    Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)1137        << getOpenMPContextTraitSelectorName(TISelector.Kind)1138        << getOpenMPContextTraitSetName(Set);1139    return FinishSelector();1140  }1141 1142  if (TISelector.Kind == TraitSelector::user_condition) {1143    SourceLocation RLoc;1144    ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);1145    if (!Condition.isUsable())1146      return FinishSelector();1147    TISelector.ScoreOrCondition = Condition.get();1148    TISelector.Properties.push_back(1149        {TraitProperty::user_condition_unknown, "<condition>"});1150    return;1151  }1152 1153  BalancedDelimiterTracker BDT(*this, tok::l_paren,1154                               tok::annot_pragma_openmp_end);1155  // Parse '('.1156  (void)BDT.consumeOpen();1157 1158  SourceLocation ScoreLoc = Tok.getLocation();1159  ExprResult Score = parseContextScore(*this);1160 1161  if (!AllowsTraitScore && !Score.isUnset()) {1162    if (Score.isUsable()) {1163      Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)1164          << getOpenMPContextTraitSelectorName(TISelector.Kind)1165          << getOpenMPContextTraitSetName(Set) << Score.get();1166    } else {1167      Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)1168          << getOpenMPContextTraitSelectorName(TISelector.Kind)1169          << getOpenMPContextTraitSetName(Set) << "<invalid>";1170    }1171    Score = ExprResult();1172  }1173 1174  if (Score.isUsable())1175    TISelector.ScoreOrCondition = Score.get();1176 1177  llvm::StringMap<SourceLocation> SeenProperties;1178  do {1179    parseOMPContextProperty(TISelector, Set, SeenProperties);1180  } while (TryConsumeToken(tok::comma));1181 1182  // Parse ')'.1183  BDT.consumeClose();1184}1185 1186void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,1187                                  llvm::StringMap<SourceLocation> &Seen) {1188  TISet.Kind = TraitSet::invalid;1189 1190  SourceLocation NameLoc = Tok.getLocation();1191  StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);1192  if (Name.empty()) {1193    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)1194        << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();1195    return;1196  }1197 1198  TISet.Kind = getOpenMPContextTraitSetKind(Name);1199  if (TISet.Kind != TraitSet::invalid) {1200    if (checkForDuplicates(*this, Name, NameLoc, Seen,1201                           CONTEXT_SELECTOR_SET_LVL))1202      TISet.Kind = TraitSet::invalid;1203    return;1204  }1205 1206  // It follows diagnosis and helping notes.1207  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;1208 1209  TraitSelector SelectorForName =1210      getOpenMPContextTraitSelectorKind(Name, TISet.Kind);1211  if (SelectorForName != TraitSelector::invalid) {1212    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)1213        << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;1214    bool AllowsTraitScore = false;1215    bool RequiresProperty = false;1216    isValidTraitSelectorForTraitSet(1217        SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),1218        AllowsTraitScore, RequiresProperty);1219    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)1220        << getOpenMPContextTraitSetName(1221               getOpenMPContextTraitSetForSelector(SelectorForName))1222        << Name << (RequiresProperty ? "(<property-name>)" : "");1223    return;1224  }1225  for (const auto &PotentialSet :1226       {TraitSet::construct, TraitSet::user, TraitSet::implementation,1227        TraitSet::device, TraitSet::target_device}) {1228    TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(1229        PotentialSet, TraitSelector::invalid, Name);1230    if (PropertyForName == TraitProperty::invalid)1231      continue;1232    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)1233        << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;1234    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)1235        << getOpenMPContextTraitSetName(1236               getOpenMPContextTraitSetForProperty(PropertyForName))1237        << getOpenMPContextTraitSelectorName(1238               getOpenMPContextTraitSelectorForProperty(PropertyForName))1239        << ("(" + Name + ")").str();1240    return;1241  }1242  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)1243      << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();1244}1245 1246void Parser::parseOMPContextSelectorSet(1247    OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {1248  auto OuterBC = BraceCount;1249 1250  // If anything went wrong we issue an error or warning and then skip the rest1251  // of the set. However, commas are ambiguous so we look for the nesting1252  // of braces here as well.1253  auto FinishSelectorSet = [this, OuterBC]() -> void {1254    bool Done = false;1255    while (!Done) {1256      while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,1257                         tok::annot_pragma_openmp_end},1258                        StopBeforeMatch))1259        ;1260      if (Tok.is(tok::r_brace) && OuterBC > BraceCount)1261        (void)ConsumeBrace();1262      if (OuterBC <= BraceCount) {1263        Done = true;1264        break;1265      }1266      if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {1267        Done = true;1268        break;1269      }1270      (void)ConsumeAnyToken();1271    }1272    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)1273        << CONTEXT_SELECTOR_SET_LVL;1274  };1275 1276  parseOMPTraitSetKind(TISet, SeenSets);1277  if (TISet.Kind == TraitSet::invalid)1278    return FinishSelectorSet();1279 1280  // Parse '='.1281  if (!TryConsumeToken(tok::equal))1282    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)1283        << "="1284        << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +1285            "\"")1286               .str();1287 1288  // Parse '{'.1289  if (Tok.is(tok::l_brace)) {1290    (void)ConsumeBrace();1291  } else {1292    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)1293        << "{"1294        << ("'=' that follows the context set name \"" +1295            getOpenMPContextTraitSetName(TISet.Kind) + "\"")1296               .str();1297  }1298 1299  llvm::StringMap<SourceLocation> SeenSelectors;1300  do {1301    OMPTraitSelector TISelector;1302    parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);1303    if (TISelector.Kind != TraitSelector::invalid &&1304        !TISelector.Properties.empty())1305      TISet.Selectors.push_back(TISelector);1306  } while (TryConsumeToken(tok::comma));1307 1308  // Parse '}'.1309  if (Tok.is(tok::r_brace)) {1310    (void)ConsumeBrace();1311  } else {1312    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)1313        << "}"1314        << ("context selectors for the context set \"" +1315            getOpenMPContextTraitSetName(TISet.Kind) + "\"")1316               .str();1317  }1318}1319 1320bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {1321  llvm::StringMap<SourceLocation> SeenSets;1322  do {1323    OMPTraitSet TISet;1324    parseOMPContextSelectorSet(TISet, SeenSets);1325    if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())1326      TI.Sets.push_back(TISet);1327  } while (TryConsumeToken(tok::comma));1328 1329  return false;1330}1331 1332void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,1333                                           CachedTokens &Toks,1334                                           SourceLocation Loc) {1335  unsigned OMPVersion = Actions.getLangOpts().OpenMP;1336  PP.EnterToken(Tok, /*IsReinject*/ true);1337  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,1338                      /*IsReinject*/ true);1339  // Consume the previously pushed token.1340  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);1341  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);1342 1343  FNContextRAII FnContext(*this, Ptr);1344  // Parse function declaration id.1345  SourceLocation RLoc;1346  // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs1347  // instead of MemberExprs.1348  ExprResult AssociatedFunction;1349  {1350    // Do not mark function as is used to prevent its emission if this is the1351    // only place where it is used.1352    EnterExpressionEvaluationContext Unevaluated(1353        Actions, Sema::ExpressionEvaluationContext::Unevaluated);1354    AssociatedFunction = ParseOpenMPParensExpr(1355        getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion), RLoc,1356        /*IsAddressOfOperand=*/true);1357  }1358  if (!AssociatedFunction.isUsable()) {1359    if (!Tok.is(tok::annot_pragma_openmp_end))1360      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))1361        ;1362    // Skip the last annot_pragma_openmp_end.1363    (void)ConsumeAnnotationToken();1364    return;1365  }1366 1367  OMPTraitInfo *ParentTI =1368      Actions.OpenMP().getOMPTraitInfoForSurroundingScope();1369  ASTContext &ASTCtx = Actions.getASTContext();1370  OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();1371  SmallVector<Expr *, 6> AdjustNothing;1372  SmallVector<Expr *, 6> AdjustNeedDevicePtr;1373  SmallVector<Expr *, 6> AdjustNeedDeviceAddr;1374  SmallVector<OMPInteropInfo, 3> AppendArgs;1375  SourceLocation AdjustArgsLoc, AppendArgsLoc;1376 1377  // At least one clause is required.1378  if (Tok.is(tok::annot_pragma_openmp_end)) {1379    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)1380        << (getLangOpts().OpenMP < 51 ? 0 : 1);1381  }1382 1383  bool IsError = false;1384  while (Tok.isNot(tok::annot_pragma_openmp_end)) {1385    OpenMPClauseKind CKind = Tok.isAnnotation()1386                                 ? OMPC_unknown1387                                 : getOpenMPClauseKind(PP.getSpelling(Tok));1388    if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,1389                                     getLangOpts().OpenMP)) {1390      Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)1391          << (getLangOpts().OpenMP < 51 ? 0 : 1);1392      IsError = true;1393    }1394    if (!IsError) {1395      switch (CKind) {1396      case OMPC_match:1397        IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);1398        break;1399      case OMPC_adjust_args: {1400        AdjustArgsLoc = Tok.getLocation();1401        ConsumeToken();1402        SemaOpenMP::OpenMPVarListDataTy Data;1403        SmallVector<Expr *> Vars;1404        IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,1405                                     Vars, Data);1406        if (!IsError) {1407          switch (Data.ExtraModifier) {1408          case OMPC_ADJUST_ARGS_nothing:1409            llvm::append_range(AdjustNothing, Vars);1410            break;1411          case OMPC_ADJUST_ARGS_need_device_ptr:1412            llvm::append_range(AdjustNeedDevicePtr, Vars);1413            break;1414          case OMPC_ADJUST_ARGS_need_device_addr:1415            llvm::append_range(AdjustNeedDeviceAddr, Vars);1416            break;1417          default:1418            llvm_unreachable("Unexpected 'adjust_args' clause modifier.");1419          }1420        }1421        break;1422      }1423      case OMPC_append_args:1424        if (!AppendArgs.empty()) {1425          Diag(AppendArgsLoc, diag::err_omp_more_one_clause)1426              << getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion)1427              << getOpenMPClauseName(CKind) << 0;1428          IsError = true;1429        }1430        if (!IsError) {1431          AppendArgsLoc = Tok.getLocation();1432          ConsumeToken();1433          IsError = parseOpenMPAppendArgs(AppendArgs);1434        }1435        break;1436      default:1437        llvm_unreachable("Unexpected clause for declare variant.");1438      }1439    }1440    if (IsError) {1441      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))1442        ;1443      // Skip the last annot_pragma_openmp_end.1444      (void)ConsumeAnnotationToken();1445      return;1446    }1447    // Skip ',' if any.1448    if (Tok.is(tok::comma))1449      ConsumeToken();1450  }1451 1452  std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =1453      Actions.OpenMP().checkOpenMPDeclareVariantFunction(1454          Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),1455          SourceRange(Loc, Tok.getLocation()));1456 1457  if (DeclVarData && !TI.Sets.empty())1458    Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(1459        DeclVarData->first, DeclVarData->second, TI, AdjustNothing,1460        AdjustNeedDevicePtr, AdjustNeedDeviceAddr, AppendArgs, AdjustArgsLoc,1461        AppendArgsLoc, SourceRange(Loc, Tok.getLocation()));1462 1463  // Skip the last annot_pragma_openmp_end.1464  (void)ConsumeAnnotationToken();1465}1466 1467bool Parser::parseOpenMPAppendArgs(1468    SmallVectorImpl<OMPInteropInfo> &InteropInfos) {1469  bool HasError = false;1470  // Parse '('.1471  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);1472  if (T.expectAndConsume(diag::err_expected_lparen_after,1473                         getOpenMPClauseName(OMPC_append_args).data()))1474    return true;1475 1476  // Parse the list of append-ops, each is;1477  // interop(interop-type[,interop-type]...)1478  while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {1479    ConsumeToken();1480    BalancedDelimiterTracker IT(*this, tok::l_paren,1481                                tok::annot_pragma_openmp_end);1482    if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))1483      return true;1484 1485    OMPInteropInfo InteropInfo;1486    if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))1487      HasError = true;1488    else1489      InteropInfos.push_back(InteropInfo);1490 1491    IT.consumeClose();1492    if (Tok.is(tok::comma))1493      ConsumeToken();1494  }1495  if (!HasError && InteropInfos.empty()) {1496    HasError = true;1497    Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);1498    SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,1499              StopBeforeMatch);1500  }1501  HasError = T.consumeClose() || HasError;1502  return HasError;1503}1504 1505bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,1506                                               OMPTraitInfo &TI,1507                                               OMPTraitInfo *ParentTI) {1508  // Parse 'match'.1509  OpenMPClauseKind CKind = Tok.isAnnotation()1510                               ? OMPC_unknown1511                               : getOpenMPClauseKind(PP.getSpelling(Tok));1512  if (CKind != OMPC_match) {1513    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)1514        << (getLangOpts().OpenMP < 51 ? 0 : 1);1515    return true;1516  }1517  (void)ConsumeToken();1518  // Parse '('.1519  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);1520  if (T.expectAndConsume(diag::err_expected_lparen_after,1521                         getOpenMPClauseName(OMPC_match).data()))1522    return true;1523 1524  // Parse inner context selectors.1525  parseOMPContextSelectors(Loc, TI);1526 1527  // Parse ')'1528  (void)T.consumeClose();1529 1530  if (!ParentTI)1531    return false;1532 1533  // Merge the parent/outer trait info into the one we just parsed and diagnose1534  // problems.1535  // TODO: Keep some source location in the TI to provide better diagnostics.1536  // TODO: Perform some kind of equivalence check on the condition and score1537  //       expressions.1538  for (const OMPTraitSet &ParentSet : ParentTI->Sets) {1539    bool MergedSet = false;1540    for (OMPTraitSet &Set : TI.Sets) {1541      if (Set.Kind != ParentSet.Kind)1542        continue;1543      MergedSet = true;1544      for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {1545        bool MergedSelector = false;1546        for (OMPTraitSelector &Selector : Set.Selectors) {1547          if (Selector.Kind != ParentSelector.Kind)1548            continue;1549          MergedSelector = true;1550          for (const OMPTraitProperty &ParentProperty :1551               ParentSelector.Properties) {1552            bool MergedProperty = false;1553            for (OMPTraitProperty &Property : Selector.Properties) {1554              // Ignore "equivalent" properties.1555              if (Property.Kind != ParentProperty.Kind)1556                continue;1557 1558              // If the kind is the same but the raw string not, we don't want1559              // to skip out on the property.1560              MergedProperty |= Property.RawString == ParentProperty.RawString;1561 1562              if (Property.RawString == ParentProperty.RawString &&1563                  Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)1564                continue;1565 1566              if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {1567                Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);1568              } else if (Selector.ScoreOrCondition !=1569                         ParentSelector.ScoreOrCondition) {1570                Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)1571                    << getOpenMPContextTraitPropertyName(1572                           ParentProperty.Kind, ParentProperty.RawString)1573                    << getOpenMPContextTraitSelectorName(ParentSelector.Kind)1574                    << getOpenMPContextTraitSetName(ParentSet.Kind);1575              }1576            }1577            if (!MergedProperty)1578              Selector.Properties.push_back(ParentProperty);1579          }1580        }1581        if (!MergedSelector)1582          Set.Selectors.push_back(ParentSelector);1583      }1584    }1585    if (!MergedSet)1586      TI.Sets.push_back(ParentSet);1587  }1588 1589  return false;1590}1591 1592void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,1593                                SmallVectorImpl<OMPClause *> &Clauses,1594                                SourceLocation Loc) {1595  std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;1596  while (Tok.isNot(tok::annot_pragma_openmp_end)) {1597    OpenMPClauseKind CKind = Tok.isAnnotation()1598                                 ? OMPC_unknown1599                                 : getOpenMPClauseKind(PP.getSpelling(Tok));1600    Actions.OpenMP().StartOpenMPClause(CKind);1601    OMPClause *Clause =1602        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);1603    SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,1604              StopBeforeMatch);1605    SeenClauses[unsigned(CKind)] = true;1606    if (Clause != nullptr)1607      Clauses.push_back(Clause);1608    if (Tok.is(tok::annot_pragma_openmp_end)) {1609      Actions.OpenMP().EndOpenMPClause();1610      break;1611    }1612    // Skip ',' if any.1613    if (Tok.is(tok::comma))1614      ConsumeToken();1615    Actions.OpenMP().EndOpenMPClause();1616  }1617}1618 1619void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,1620                                         SourceLocation Loc) {1621  SmallVector<std::string, 4> Assumptions;1622  bool SkippedClauses = false;1623 1624  auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {1625    BalancedDelimiterTracker T(*this, tok::l_paren,1626                               tok::annot_pragma_openmp_end);1627    if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))1628      return;1629    T.skipToEnd();1630    if (IssueNote && T.getCloseLocation().isValid())1631      Diag(T.getCloseLocation(),1632           diag::note_omp_assumption_clause_continue_here);1633  };1634 1635  /// Helper to determine which AssumptionClauseMapping (ACM) in the1636  /// AssumptionClauseMappings table matches \p RawString. The return value is1637  /// the index of the matching ACM into the table or -1 if there was no match.1638  auto MatchACMClause = [&](StringRef RawString) {1639    llvm::StringSwitch<int> SS(RawString);1640    unsigned ACMIdx = 0;1641    for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {1642      if (ACMI.StartsWith)1643        SS.StartsWith(ACMI.Identifier, ACMIdx++);1644      else1645        SS.Case(ACMI.Identifier, ACMIdx++);1646    }1647    return SS.Default(-1);1648  };1649 1650  while (Tok.isNot(tok::annot_pragma_openmp_end)) {1651    IdentifierInfo *II = nullptr;1652    SourceLocation StartLoc = Tok.getLocation();1653    int Idx = -1;1654    if (Tok.isAnyIdentifier()) {1655      II = Tok.getIdentifierInfo();1656      Idx = MatchACMClause(II->getName());1657    }1658    ConsumeAnyToken();1659 1660    bool NextIsLPar = Tok.is(tok::l_paren);1661    // Handle unknown clauses by skipping them.1662    if (Idx == -1) {1663      unsigned OMPVersion = Actions.getLangOpts().OpenMP;1664      Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)1665          << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion)1666          << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;1667      if (NextIsLPar)1668        SkipBraces(II ? II->getName() : "", /* IssueNote */ true);1669      SkippedClauses = true;1670      continue;1671    }1672    const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];1673    if (ACMI.HasDirectiveList || ACMI.HasExpression) {1674      // TODO: We ignore absent, contains, and holds assumptions for now. We1675      //       also do not verify the content in the parenthesis at all.1676      SkippedClauses = true;1677      SkipBraces(II->getName(), /* IssueNote */ false);1678      continue;1679    }1680 1681    if (NextIsLPar) {1682      Diag(Tok.getLocation(),1683           diag::warn_omp_unknown_assumption_clause_without_args)1684          << II;1685      SkipBraces(II->getName(), /* IssueNote */ true);1686    }1687 1688    assert(II && "Expected an identifier clause!");1689    std::string Assumption = II->getName().str();1690    if (ACMI.StartsWith)1691      Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());1692    else1693      Assumption = "omp_" + Assumption;1694    Assumptions.push_back(Assumption);1695  }1696 1697  Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,1698                                               SkippedClauses);1699}1700 1701void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {1702  if (Actions.OpenMP().isInOpenMPAssumeScope())1703    Actions.OpenMP().ActOnOpenMPEndAssumesDirective();1704  else1705    Diag(Loc, diag::err_expected_begin_assumes);1706}1707 1708/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.1709///1710///    default-clause:1711///         'default' '(' 'none' | 'shared'  | 'private' | 'firstprivate' ')1712///1713///    proc_bind-clause:1714///         'proc_bind' '(' 'master' | 'close' | 'spread' ')1715///1716///    device_type-clause:1717///         'device_type' '(' 'host' | 'nohost' | 'any' )'1718namespace {1719struct SimpleClauseData {1720  unsigned Type;1721  SourceLocation Loc;1722  SourceLocation LOpen;1723  SourceLocation TypeLoc;1724  SourceLocation RLoc;1725  SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,1726                   SourceLocation TypeLoc, SourceLocation RLoc)1727      : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}1728};1729} // anonymous namespace1730 1731static std::optional<SimpleClauseData>1732parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {1733  const Token &Tok = P.getCurToken();1734  SourceLocation Loc = Tok.getLocation();1735  SourceLocation LOpen = P.ConsumeToken();1736  // Parse '('.1737  BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);1738  if (T.expectAndConsume(diag::err_expected_lparen_after,1739                         getOpenMPClauseName(Kind).data()))1740    return std::nullopt;1741 1742  unsigned Type = getOpenMPSimpleClauseType(1743      Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),1744      P.getLangOpts());1745  SourceLocation TypeLoc = Tok.getLocation();1746  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&1747      Tok.isNot(tok::annot_pragma_openmp_end))1748    P.ConsumeAnyToken();1749 1750  // Parse ')'.1751  SourceLocation RLoc = Tok.getLocation();1752  if (!T.consumeClose())1753    RLoc = T.getCloseLocation();1754 1755  return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);1756}1757 1758void Parser::ParseOMPDeclareTargetClauses(1759    SemaOpenMP::DeclareTargetContextInfo &DTCI) {1760  SourceLocation DeviceTypeLoc;1761  bool RequiresToOrLinkOrIndirectClause = false;1762  bool HasToOrLinkOrIndirectClause = false;1763  while (Tok.isNot(tok::annot_pragma_openmp_end)) {1764    OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;1765    bool HasIdentifier = Tok.is(tok::identifier);1766    if (HasIdentifier) {1767      // If we see any clause we need a to or link clause.1768      RequiresToOrLinkOrIndirectClause = true;1769      IdentifierInfo *II = Tok.getIdentifierInfo();1770      StringRef ClauseName = II->getName();1771      bool IsDeviceTypeClause =1772          getLangOpts().OpenMP >= 50 &&1773          getOpenMPClauseKind(ClauseName) == OMPC_device_type;1774 1775      bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&1776                              getOpenMPClauseKind(ClauseName) == OMPC_indirect;1777      if (DTCI.Indirect && IsIndirectClause) {1778        unsigned OMPVersion = Actions.getLangOpts().OpenMP;1779        Diag(Tok, diag::err_omp_more_one_clause)1780            << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)1781            << getOpenMPClauseName(OMPC_indirect) << 0;1782        break;1783      }1784      bool IsToEnterOrLinkClause =1785          OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);1786      assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&1787             "Cannot be both!");1788 1789      // Starting with OpenMP 5.2 the `to` clause has been replaced by the1790      // `enter` clause.1791      if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {1792        Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);1793        break;1794      }1795      if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {1796        Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);1797        break;1798      }1799 1800      if (!IsDeviceTypeClause && !IsIndirectClause &&1801          DTCI.Kind == OMPD_begin_declare_target) {1802        Diag(Tok, diag::err_omp_declare_target_unexpected_clause)1803            << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);1804        break;1805      }1806      if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {1807        Diag(Tok, getLangOpts().OpenMP >= 521808                      ? diag::err_omp_declare_target_unexpected_clause_521809                      : diag::err_omp_declare_target_unexpected_clause)1810            << ClauseName1811            << (getLangOpts().OpenMP >= 511812                    ? 41813                    : getLangOpts().OpenMP >= 50 ? 2 : 1);1814        break;1815      }1816 1817      if (IsToEnterOrLinkClause || IsIndirectClause)1818        HasToOrLinkOrIndirectClause = true;1819 1820      if (IsIndirectClause) {1821        if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))1822          break;1823        continue;1824      }1825      // Parse 'device_type' clause and go to next clause if any.1826      if (IsDeviceTypeClause) {1827        std::optional<SimpleClauseData> DevTypeData =1828            parseOpenMPSimpleClause(*this, OMPC_device_type);1829        if (DevTypeData) {1830          if (DeviceTypeLoc.isValid()) {1831            // We already saw another device_type clause, diagnose it.1832            Diag(DevTypeData->Loc,1833                 diag::warn_omp_more_one_device_type_clause);1834            break;1835          }1836          switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {1837          case OMPC_DEVICE_TYPE_any:1838            DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;1839            break;1840          case OMPC_DEVICE_TYPE_host:1841            DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;1842            break;1843          case OMPC_DEVICE_TYPE_nohost:1844            DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;1845            break;1846          case OMPC_DEVICE_TYPE_unknown:1847            llvm_unreachable("Unexpected device_type");1848          }1849          DeviceTypeLoc = DevTypeData->Loc;1850        }1851        continue;1852      }1853      ConsumeToken();1854    }1855 1856    if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {1857      auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,1858                                          DeclarationNameInfo NameInfo) {1859        NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(1860            getCurScope(), SS, NameInfo);1861        if (!ND)1862          return;1863        SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};1864        bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;1865        if (!FirstMapping)1866          Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)1867              << NameInfo.getName();1868      };1869      if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,1870                                   /*AllowScopeSpecifier=*/true))1871        break;1872    }1873 1874    if (Tok.is(tok::l_paren)) {1875      Diag(Tok,1876           diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);1877      break;1878    }1879    if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {1880      Diag(Tok,1881           getLangOpts().OpenMP >= 521882               ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter1883               : diag::err_omp_declare_target_wrong_clause_after_implicit_to);1884      break;1885    }1886 1887    // Consume optional ','.1888    if (Tok.is(tok::comma))1889      ConsumeToken();1890  }1891 1892  if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)1893    Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);1894 1895  // For declare target require at least 'to' or 'link' to be present.1896  if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&1897      !HasToOrLinkOrIndirectClause)1898    Diag(DTCI.Loc,1899         getLangOpts().OpenMP >= 521900             ? diag::err_omp_declare_target_missing_enter_or_link_clause1901             : diag::err_omp_declare_target_missing_to_or_link_clause)1902        << (getLangOpts().OpenMP >= 51 ? 1 : 0);1903 1904  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);1905}1906 1907void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {1908  // The last seen token is annot_pragma_openmp_end - need to check for1909  // extra tokens.1910  if (Tok.is(tok::annot_pragma_openmp_end))1911    return;1912 1913  unsigned OMPVersion = Actions.getLangOpts().OpenMP;1914  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)1915      << getOpenMPDirectiveName(DKind, OMPVersion);1916  while (Tok.isNot(tok::annot_pragma_openmp_end))1917    ConsumeAnyToken();1918}1919 1920void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,1921                                  OpenMPDirectiveKind ExpectedKind,1922                                  OpenMPDirectiveKind FoundKind,1923                                  SourceLocation BeginLoc,1924                                  SourceLocation FoundLoc,1925                                  bool SkipUntilOpenMPEnd) {1926  int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;1927 1928  if (FoundKind == ExpectedKind) {1929    ConsumeAnyToken();1930    skipUntilPragmaOpenMPEnd(ExpectedKind);1931    return;1932  }1933 1934  unsigned OMPVersion = Actions.getLangOpts().OpenMP;1935  Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)1936      << DiagSelection;1937  Diag(BeginLoc, diag::note_matching)1938      << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + "'")1939             .str();1940  if (SkipUntilOpenMPEnd)1941    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);1942}1943 1944void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,1945                                               OpenMPDirectiveKind EndDKind,1946                                               SourceLocation DKLoc) {1947  parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,1948                       Tok.getLocation(),1949                       /* SkipUntilOpenMPEnd */ false);1950  // Skip the last annot_pragma_openmp_end.1951  if (Tok.is(tok::annot_pragma_openmp_end))1952    ConsumeAnnotationToken();1953}1954 1955Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(1956    AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,1957    DeclSpec::TST TagType, Decl *Tag) {1958  assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&1959         "Not an OpenMP directive!");1960  ParsingOpenMPDirectiveRAII DirScope(*this);1961  ParenBraceBracketBalancer BalancerRAIIObj(*this);1962  unsigned OMPVersion = Actions.getLangOpts().OpenMP;1963 1964  SourceLocation Loc;1965  OpenMPDirectiveKind DKind;1966  if (Delayed) {1967    TentativeParsingAction TPA(*this);1968    Loc = ConsumeAnnotationToken();1969    DKind = parseOpenMPDirectiveKind(*this);1970    if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {1971      // Need to delay parsing until completion of the parent class.1972      TPA.Revert();1973      CachedTokens Toks;1974      unsigned Cnt = 1;1975      Toks.push_back(Tok);1976      while (Cnt && Tok.isNot(tok::eof)) {1977        (void)ConsumeAnyToken();1978        if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))1979          ++Cnt;1980        else if (Tok.is(tok::annot_pragma_openmp_end))1981          --Cnt;1982        Toks.push_back(Tok);1983      }1984      // Skip last annot_pragma_openmp_end.1985      if (Cnt == 0)1986        (void)ConsumeAnyToken();1987      auto *LP = new LateParsedPragma(this, AS);1988      LP->takeToks(Toks);1989      getCurrentClass().LateParsedDeclarations.push_back(LP);1990      return nullptr;1991    }1992    TPA.Commit();1993  } else {1994    Loc = ConsumeAnnotationToken();1995    DKind = parseOpenMPDirectiveKind(*this);1996  }1997 1998  switch (DKind) {1999  case OMPD_threadprivate: {2000    ConsumeToken();2001    DeclDirectiveListParserHelper Helper(this, DKind);2002    if (!ParseOpenMPSimpleVarList(DKind, Helper,2003                                  /*AllowScopeSpecifier=*/true)) {2004      skipUntilPragmaOpenMPEnd(DKind);2005      // Skip the last annot_pragma_openmp_end.2006      ConsumeAnnotationToken();2007      return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(2008          Loc, Helper.getIdentifiers());2009    }2010    break;2011  }2012  case OMPD_groupprivate: {2013    ConsumeToken();2014    DeclDirectiveListParserHelper Helper(this, DKind);2015    if (!ParseOpenMPSimpleVarList(DKind, Helper,2016                                  /*AllowScopeSpecifier=*/true)) {2017      skipUntilPragmaOpenMPEnd(DKind);2018      // Skip the last annot_pragma_openmp_end.2019      ConsumeAnnotationToken();2020      return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(2021          Loc, Helper.getIdentifiers());2022    }2023    break;2024  }2025  case OMPD_allocate: {2026    ConsumeToken();2027    DeclDirectiveListParserHelper Helper(this, DKind);2028    if (!ParseOpenMPSimpleVarList(DKind, Helper,2029                                  /*AllowScopeSpecifier=*/true)) {2030      SmallVector<OMPClause *, 1> Clauses;2031      if (Tok.isNot(tok::annot_pragma_openmp_end)) {2032        std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;2033        while (Tok.isNot(tok::annot_pragma_openmp_end)) {2034          OpenMPClauseKind CKind =2035              Tok.isAnnotation() ? OMPC_unknown2036                                 : getOpenMPClauseKind(PP.getSpelling(Tok));2037          Actions.OpenMP().StartOpenMPClause(CKind);2038          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,2039                                                !SeenClauses[unsigned(CKind)]);2040          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,2041                    StopBeforeMatch);2042          SeenClauses[unsigned(CKind)] = true;2043          if (Clause != nullptr)2044            Clauses.push_back(Clause);2045          if (Tok.is(tok::annot_pragma_openmp_end)) {2046            Actions.OpenMP().EndOpenMPClause();2047            break;2048          }2049          // Skip ',' if any.2050          if (Tok.is(tok::comma))2051            ConsumeToken();2052          Actions.OpenMP().EndOpenMPClause();2053        }2054        skipUntilPragmaOpenMPEnd(DKind);2055      }2056      // Skip the last annot_pragma_openmp_end.2057      ConsumeAnnotationToken();2058      return Actions.OpenMP().ActOnOpenMPAllocateDirective(2059          Loc, Helper.getIdentifiers(), Clauses);2060    }2061    break;2062  }2063  case OMPD_requires: {2064    SourceLocation StartLoc = ConsumeToken();2065    SmallVector<OMPClause *, 5> Clauses;2066    llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);2067    if (Tok.is(tok::annot_pragma_openmp_end)) {2068      Diag(Tok, diag::err_omp_expected_clause)2069          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);2070      break;2071    }2072    while (Tok.isNot(tok::annot_pragma_openmp_end)) {2073      OpenMPClauseKind CKind = Tok.isAnnotation()2074                                   ? OMPC_unknown2075                                   : getOpenMPClauseKind(PP.getSpelling(Tok));2076      Actions.OpenMP().StartOpenMPClause(CKind);2077      OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,2078                                            !SeenClauses[unsigned(CKind)]);2079      SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,2080                StopBeforeMatch);2081      SeenClauses[unsigned(CKind)] = true;2082      if (Clause != nullptr)2083        Clauses.push_back(Clause);2084      if (Tok.is(tok::annot_pragma_openmp_end)) {2085        Actions.OpenMP().EndOpenMPClause();2086        break;2087      }2088      // Skip ',' if any.2089      if (Tok.is(tok::comma))2090        ConsumeToken();2091      Actions.OpenMP().EndOpenMPClause();2092    }2093    // Consume final annot_pragma_openmp_end2094    if (Clauses.empty()) {2095      Diag(Tok, diag::err_omp_expected_clause)2096          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);2097      ConsumeAnnotationToken();2098      return nullptr;2099    }2100    ConsumeAnnotationToken();2101    return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);2102  }2103  case OMPD_error: {2104    SmallVector<OMPClause *, 1> Clauses;2105    SourceLocation StartLoc = ConsumeToken();2106    ParseOpenMPClauses(DKind, Clauses, StartLoc);2107    Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,2108                                               SourceLocation(),2109                                               /*InExContext = */ false);2110    break;2111  }2112  case OMPD_assumes:2113  case OMPD_begin_assumes:2114    ParseOpenMPAssumesDirective(DKind, ConsumeToken());2115    break;2116  case OMPD_end_assumes:2117    ParseOpenMPEndAssumesDirective(ConsumeToken());2118    break;2119  case OMPD_declare_reduction:2120    ConsumeToken();2121    if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {2122      skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);2123      // Skip the last annot_pragma_openmp_end.2124      ConsumeAnnotationToken();2125      return Res;2126    }2127    break;2128  case OMPD_declare_mapper: {2129    ConsumeToken();2130    if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {2131      // Skip the last annot_pragma_openmp_end.2132      ConsumeAnnotationToken();2133      return Res;2134    }2135    break;2136  }2137  case OMPD_begin_declare_variant: {2138    ConsumeToken();2139    if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {2140      // Skip the last annot_pragma_openmp_end.2141      if (!isEofOrEom())2142        ConsumeAnnotationToken();2143    }2144    return nullptr;2145  }2146  case OMPD_end_declare_variant: {2147    ConsumeToken();2148    if (Actions.OpenMP().isInOpenMPDeclareVariantScope())2149      Actions.OpenMP().ActOnOpenMPEndDeclareVariant();2150    else2151      Diag(Loc, diag::err_expected_begin_declare_variant);2152    // Skip the last annot_pragma_openmp_end.2153    ConsumeAnnotationToken();2154    return nullptr;2155  }2156  case OMPD_declare_variant:2157  case OMPD_declare_simd: {2158    // The syntax is:2159    // { #pragma omp declare {simd|variant} }2160    // <function-declaration-or-definition>2161    //2162    CachedTokens Toks;2163    Toks.push_back(Tok);2164    ConsumeToken();2165    while (Tok.isNot(tok::annot_pragma_openmp_end)) {2166      Toks.push_back(Tok);2167      ConsumeAnyToken();2168    }2169    Toks.push_back(Tok);2170    ConsumeAnyToken();2171 2172    DeclGroupPtrTy Ptr;2173    if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {2174      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,2175                                                       TagType, Tag);2176    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {2177      // Here we expect to see some function declaration.2178      if (AS == AS_none) {2179        assert(TagType == DeclSpec::TST_unspecified);2180        ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);2181        MaybeParseCXX11Attributes(Attrs);2182        ParsingDeclSpec PDS(*this);2183        Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);2184      } else {2185        Ptr =2186            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);2187      }2188    }2189    if (!Ptr) {2190      Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)2191          << (DKind == OMPD_declare_simd ? 0 : 1);2192      return DeclGroupPtrTy();2193    }2194    if (DKind == OMPD_declare_simd)2195      return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);2196    assert(DKind == OMPD_declare_variant &&2197           "Expected declare variant directive only");2198    ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);2199    return Ptr;2200  }2201  case OMPD_begin_declare_target:2202  case OMPD_declare_target: {2203    SourceLocation DTLoc = ConsumeAnyToken();2204    bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);2205    SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);2206    if (DKind == OMPD_declare_target && !HasClauses &&2207        getLangOpts().OpenMP >= 52)2208      Diag(DTLoc, diag::warn_omp_deprecated_declare_target_delimited_form);2209    if (HasClauses)2210      ParseOMPDeclareTargetClauses(DTCI);2211    bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||2212                               !HasClauses ||2213                               (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);2214 2215    // Skip the last annot_pragma_openmp_end.2216    ConsumeAnyToken();2217 2218    if (HasImplicitMappings) {2219      Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);2220      return nullptr;2221    }2222 2223    Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);2224    llvm::SmallVector<Decl *, 4> Decls;2225    for (auto &It : DTCI.ExplicitlyMapped)2226      Decls.push_back(It.first);2227    return Actions.BuildDeclaratorGroup(Decls);2228  }2229  case OMPD_end_declare_target: {2230    if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {2231      Diag(Tok, diag::err_omp_unexpected_directive)2232          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);2233      break;2234    }2235    const SemaOpenMP::DeclareTargetContextInfo &DTCI =2236        Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();2237    ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);2238    return nullptr;2239  }2240  case OMPD_assume: {2241    Diag(Tok, diag::err_omp_unexpected_directive)2242        << 1 << getOpenMPDirectiveName(DKind, OMPVersion);2243    break;2244  }2245  case OMPD_unknown:2246    Diag(Tok, diag::err_omp_unknown_directive);2247    break;2248  default:2249    switch (getDirectiveCategory(DKind)) {2250    case Category::Executable:2251    case Category::Meta:2252    case Category::Subsidiary:2253    case Category::Utility:2254      Diag(Tok, diag::err_omp_unexpected_directive)2255          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);2256      break;2257    case Category::Declarative:2258    case Category::Informational:2259      break;2260    }2261  }2262  while (Tok.isNot(tok::annot_pragma_openmp_end))2263    ConsumeAnyToken();2264  ConsumeAnyToken();2265  return nullptr;2266}2267 2268StmtResult Parser::ParseOpenMPExecutableDirective(2269    ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,2270    bool ReadDirectiveWithinMetadirective) {2271  assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");2272  unsigned OMPVersion = Actions.getLangOpts().OpenMP;2273 2274  bool HasAssociatedStatement = true;2275  Association Assoc = getDirectiveAssociation(DKind);2276 2277  // OMPD_ordered has None as association, but it comes in two variants,2278  // the second of which is associated with a block.2279  // OMPD_scan and OMPD_section are both "separating", but section is treated2280  // as if it was associated with a statement, while scan is not.2281  if (DKind != OMPD_ordered && DKind != OMPD_section &&2282      (Assoc == Association::None || Assoc == Association::Separating)) {2283    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==2284        ParsedStmtContext()) {2285      Diag(Tok, diag::err_omp_immediate_directive)2286          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;2287      if (DKind == OMPD_error) {2288        SkipUntil(tok::annot_pragma_openmp_end);2289        return StmtError();2290      }2291    }2292    HasAssociatedStatement = false;2293  }2294 2295  SourceLocation EndLoc;2296  SmallVector<OMPClause *, 5> Clauses;2297  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);2298  DeclarationNameInfo DirName;2299  OpenMPDirectiveKind CancelRegion = OMPD_unknown;2300  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |2301                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;2302 2303  // Special processing for flush and depobj clauses.2304  Token ImplicitTok;2305  bool ImplicitClauseAllowed = false;2306  if (DKind == OMPD_flush || DKind == OMPD_depobj) {2307    ImplicitTok = Tok;2308    ImplicitClauseAllowed = true;2309  }2310  ConsumeToken();2311  // Parse directive name of the 'critical' directive if any.2312  if (DKind == OMPD_critical) {2313    BalancedDelimiterTracker T(*this, tok::l_paren,2314                               tok::annot_pragma_openmp_end);2315    if (!T.consumeOpen()) {2316      if (Tok.isAnyIdentifier()) {2317        DirName =2318            DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());2319        ConsumeAnyToken();2320      } else {2321        Diag(Tok, diag::err_omp_expected_identifier_for_critical);2322      }2323      T.consumeClose();2324    }2325  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {2326    CancelRegion = parseOpenMPDirectiveKind(*this);2327    if (Tok.isNot(tok::annot_pragma_openmp_end))2328      ConsumeAnyToken();2329  }2330 2331  if (isOpenMPLoopDirective(DKind))2332    ScopeFlags |= Scope::OpenMPLoopDirectiveScope;2333  if (isOpenMPSimdDirective(DKind))2334    ScopeFlags |= Scope::OpenMPSimdDirectiveScope;2335  ParseScope OMPDirectiveScope(this, ScopeFlags);2336  Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),2337                                       Loc);2338 2339  while (Tok.isNot(tok::annot_pragma_openmp_end)) {2340    // If we are parsing for a directive within a metadirective, the directive2341    // ends with a ')'.2342    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {2343      while (Tok.isNot(tok::annot_pragma_openmp_end))2344        ConsumeAnyToken();2345      break;2346    }2347    bool HasImplicitClause = false;2348    if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {2349      HasImplicitClause = true;2350      // Push copy of the current token back to stream to properly parse2351      // pseudo-clause OMPFlushClause or OMPDepobjClause.2352      PP.EnterToken(Tok, /*IsReinject*/ true);2353      PP.EnterToken(ImplicitTok, /*IsReinject*/ true);2354      ConsumeAnyToken();2355    }2356    OpenMPClauseKind CKind = Tok.isAnnotation()2357                                 ? OMPC_unknown2358                                 : getOpenMPClauseKind(PP.getSpelling(Tok));2359    if (HasImplicitClause) {2360      assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");2361      if (DKind == OMPD_flush) {2362        CKind = OMPC_flush;2363      } else {2364        assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");2365        CKind = OMPC_depobj;2366      }2367    }2368    // No more implicit clauses allowed.2369    ImplicitClauseAllowed = false;2370    Actions.OpenMP().StartOpenMPClause(CKind);2371    HasImplicitClause = false;2372    OMPClause *Clause =2373        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);2374    SeenClauses[unsigned(CKind)] = true;2375    if (Clause)2376      Clauses.push_back(Clause);2377 2378    // Skip ',' if any.2379    if (Tok.is(tok::comma))2380      ConsumeToken();2381    Actions.OpenMP().EndOpenMPClause();2382  }2383  // End location of the directive.2384  EndLoc = Tok.getLocation();2385  // Consume final annot_pragma_openmp_end.2386  ConsumeAnnotationToken();2387 2388  if (DKind == OMPD_ordered) {2389    // If the depend or doacross clause is specified, the ordered construct2390    // is a stand-alone directive.2391    for (auto CK : {OMPC_depend, OMPC_doacross}) {2392      if (SeenClauses[unsigned(CK)]) {2393        if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==2394            ParsedStmtContext()) {2395          Diag(Loc, diag::err_omp_immediate_directive)2396              << getOpenMPDirectiveName(DKind, OMPVersion) << 12397              << getOpenMPClauseName(CK);2398        }2399        HasAssociatedStatement = false;2400      }2401    }2402  }2403 2404  if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&2405      !SeenClauses[unsigned(OMPC_sizes)]) {2406    Diag(Loc, diag::err_omp_required_clause)2407        << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";2408  }2409 2410  StmtResult AssociatedStmt;2411  if (HasAssociatedStatement) {2412    // The body is a block scope like in Lambdas and Blocks.2413    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());2414    // FIXME: We create a bogus CompoundStmt scope to hold the contents of2415    // the captured region. Code elsewhere assumes that any FunctionScopeInfo2416    // should have at least one compound statement scope within it.2417    ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);2418    {2419      Sema::CompoundScopeRAII Scope(Actions);2420      AssociatedStmt = ParseStatement();2421 2422      if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&2423          getLangOpts().OpenMPIRBuilder)2424        AssociatedStmt =2425            Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());2426    }2427    AssociatedStmt =2428        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);2429  } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||2430             DKind == OMPD_target_exit_data) {2431    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());2432    AssociatedStmt = (Sema::CompoundScopeRAII(Actions),2433                      Actions.ActOnCompoundStmt(Loc, Loc, {},2434                                                /*isStmtExpr=*/false));2435    AssociatedStmt =2436        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);2437  }2438 2439  StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(2440      DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);2441 2442  // Exit scope.2443  Actions.OpenMP().EndOpenMPDSABlock(Directive.get());2444  OMPDirectiveScope.Exit();2445 2446  return Directive;2447}2448 2449StmtResult Parser::ParseOpenMPInformationalDirective(2450    ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,2451    bool ReadDirectiveWithinMetadirective) {2452  assert(isOpenMPInformationalDirective(DKind) &&2453         "Unexpected directive category");2454 2455  bool HasAssociatedStatement = true;2456 2457  SmallVector<OMPClause *, 5> Clauses;2458  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);2459  DeclarationNameInfo DirName;2460  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |2461                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;2462  ParseScope OMPDirectiveScope(this, ScopeFlags);2463 2464  Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),2465                                       Loc);2466 2467  while (Tok.isNot(tok::annot_pragma_openmp_end)) {2468    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {2469      while (Tok.isNot(tok::annot_pragma_openmp_end))2470        ConsumeAnyToken();2471      break;2472    }2473 2474    OpenMPClauseKind CKind = Tok.isAnnotation()2475                                 ? OMPC_unknown2476                                 : getOpenMPClauseKind(PP.getSpelling(Tok));2477    Actions.OpenMP().StartOpenMPClause(CKind);2478    OMPClause *Clause =2479        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);2480    SeenClauses[unsigned(CKind)] = true;2481    if (Clause)2482      Clauses.push_back(Clause);2483 2484    if (Tok.is(tok::comma))2485      ConsumeToken();2486    Actions.OpenMP().EndOpenMPClause();2487  }2488 2489  SourceLocation EndLoc = Tok.getLocation();2490  ConsumeAnnotationToken();2491 2492  StmtResult AssociatedStmt;2493  if (HasAssociatedStatement) {2494    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());2495    ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);2496    {2497      Sema::CompoundScopeRAII Scope(Actions);2498      AssociatedStmt = ParseStatement();2499    }2500    AssociatedStmt =2501        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);2502  }2503 2504  StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(2505      DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);2506 2507  Actions.OpenMP().EndOpenMPDSABlock(Directive.get());2508  OMPDirectiveScope.Exit();2509 2510  return Directive;2511}2512 2513StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(2514    ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {2515  if (!ReadDirectiveWithinMetadirective)2516    assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&2517           "Not an OpenMP directive!");2518  ParsingOpenMPDirectiveRAII DirScope(*this);2519  ParenBraceBracketBalancer BalancerRAIIObj(*this);2520  SourceLocation Loc = ReadDirectiveWithinMetadirective2521                           ? Tok.getLocation()2522                           : ConsumeAnnotationToken();2523  unsigned OMPVersion = Actions.getLangOpts().OpenMP;2524  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);2525  if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {2526    Diag(Tok, diag::err_omp_unknown_directive);2527    return StmtError();2528  }2529 2530  StmtResult Directive = StmtError();2531 2532  bool IsExecutable = [&]() {2533    if (DKind == OMPD_error) // OMPD_error is handled as executable2534      return true;2535    auto Res = getDirectiveCategory(DKind);2536    return Res == Category::Executable || Res == Category::Subsidiary;2537  }();2538 2539  if (IsExecutable) {2540    Directive = ParseOpenMPExecutableDirective(2541        StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);2542    assert(!Directive.isUnset() && "Executable directive remained unprocessed");2543    return Directive;2544  }2545 2546  switch (DKind) {2547  case OMPD_nothing:2548    ConsumeToken();2549    // If we are parsing the directive within a metadirective, the directive2550    // ends with a ')'.2551    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))2552      while (Tok.isNot(tok::annot_pragma_openmp_end))2553        ConsumeAnyToken();2554    else2555      skipUntilPragmaOpenMPEnd(DKind);2556    if (Tok.is(tok::annot_pragma_openmp_end))2557      ConsumeAnnotationToken();2558    // return an empty statement2559    return StmtEmpty();2560  case OMPD_metadirective: {2561    ConsumeToken();2562    SmallVector<VariantMatchInfo, 4> VMIs;2563 2564    // First iteration of parsing all clauses of metadirective.2565    // This iteration only parses and collects all context selector ignoring the2566    // associated directives.2567    TentativeParsingAction TPA(*this);2568    ASTContext &ASTContext = Actions.getASTContext();2569 2570    BalancedDelimiterTracker T(*this, tok::l_paren,2571                               tok::annot_pragma_openmp_end);2572    while (Tok.isNot(tok::annot_pragma_openmp_end)) {2573      OpenMPClauseKind CKind = Tok.isAnnotation()2574                                   ? OMPC_unknown2575                                   : getOpenMPClauseKind(PP.getSpelling(Tok));2576      // Check if the clause is unrecognized.2577      if (CKind == OMPC_unknown) {2578        Diag(Tok, diag::err_omp_expected_clause) << "metadirective";2579        TPA.Revert();2580        SkipUntil(tok::annot_pragma_openmp_end);2581        return Directive;2582      }2583      if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)2584        Diag(Tok, diag::err_omp_unexpected_clause)2585            << getOpenMPClauseName(CKind) << "metadirective";2586      if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)2587        Diag(Tok, diag::warn_omp_default_deprecated);2588 2589      SourceLocation Loc = ConsumeToken();2590 2591      // Parse '('.2592      if (T.expectAndConsume(diag::err_expected_lparen_after,2593                             getOpenMPClauseName(CKind).data())) {2594        TPA.Revert();2595        SkipUntil(tok::annot_pragma_openmp_end);2596        return Directive;2597      }2598 2599      OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();2600      if (CKind == OMPC_when) {2601        // parse and get OMPTraitInfo to pass to the When clause2602        parseOMPContextSelectors(Loc, TI);2603        if (TI.Sets.size() == 0) {2604          Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";2605          TPA.Commit();2606          return Directive;2607        }2608 2609        // Parse ':'2610        if (Tok.is(tok::colon))2611          ConsumeAnyToken();2612        else {2613          Diag(Tok, diag::err_omp_expected_colon) << "when clause";2614          TPA.Commit();2615          return Directive;2616        }2617      }2618 2619      // Skip Directive for now. We will parse directive in the second iteration2620      int paren = 0;2621      while (Tok.isNot(tok::r_paren) || paren != 0) {2622        if (Tok.is(tok::l_paren))2623          paren++;2624        if (Tok.is(tok::r_paren))2625          paren--;2626        if (Tok.is(tok::annot_pragma_openmp_end)) {2627          Diag(Tok, diag::err_omp_expected_punc)2628              << getOpenMPClauseName(CKind) << 0;2629          TPA.Commit();2630          return Directive;2631        }2632        ConsumeAnyToken();2633      }2634      // Parse ')'2635      if (Tok.is(tok::r_paren))2636        T.consumeClose();2637 2638      VariantMatchInfo VMI;2639      TI.getAsVariantMatchInfo(ASTContext, VMI);2640 2641      VMIs.push_back(VMI);2642    }2643 2644    TPA.Revert();2645    // End of the first iteration. Parser is reset to the start of metadirective2646 2647    std::function<void(StringRef)> DiagUnknownTrait =2648        [this, Loc](StringRef ISATrait) {2649          // TODO Track the selector locations in a way that is accessible here2650          // to improve the diagnostic location.2651          Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;2652        };2653    TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),2654                            /* CurrentFunctionDecl */ nullptr,2655                            ArrayRef<llvm::omp::TraitProperty>(),2656                            Actions.OpenMP().getOpenMPDeviceNum());2657 2658    // A single match is returned for OpenMP 5.02659    int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);2660 2661    int Idx = 0;2662    // In OpenMP 5.0 metadirective is either replaced by another directive or2663    // ignored.2664    // TODO: In OpenMP 5.1 generate multiple directives based upon the matches2665    // found by getBestWhenMatchForContext.2666    while (Tok.isNot(tok::annot_pragma_openmp_end)) {2667      // OpenMP 5.0 implementation - Skip to the best index found.2668      if (Idx++ != BestIdx) {2669        ConsumeToken();  // Consume clause name2670        T.consumeOpen(); // Consume '('2671        int paren = 0;2672        // Skip everything inside the clause2673        while (Tok.isNot(tok::r_paren) || paren != 0) {2674          if (Tok.is(tok::l_paren))2675            paren++;2676          if (Tok.is(tok::r_paren))2677            paren--;2678          ConsumeAnyToken();2679        }2680        // Parse ')'2681        if (Tok.is(tok::r_paren))2682          T.consumeClose();2683        continue;2684      }2685 2686      OpenMPClauseKind CKind = Tok.isAnnotation()2687                                   ? OMPC_unknown2688                                   : getOpenMPClauseKind(PP.getSpelling(Tok));2689      SourceLocation Loc = ConsumeToken();2690 2691      // Parse '('.2692      T.consumeOpen();2693 2694      // Skip ContextSelectors for when clause2695      if (CKind == OMPC_when) {2696        OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();2697        // parse and skip the ContextSelectors2698        parseOMPContextSelectors(Loc, TI);2699 2700        // Parse ':'2701        ConsumeAnyToken();2702      }2703 2704      // If no directive is passed, skip in OpenMP 5.0.2705      // TODO: Generate nothing directive from OpenMP 5.1.2706      if (Tok.is(tok::r_paren)) {2707        SkipUntil(tok::annot_pragma_openmp_end);2708        break;2709      }2710 2711      // Parse Directive2712      Directive = ParseOpenMPDeclarativeOrExecutableDirective(2713          StmtCtx,2714          /*ReadDirectiveWithinMetadirective=*/true);2715      break;2716    }2717    // If no match is found and no otherwise clause is present, skip2718    // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as2719    // if one was specified without an associated directive variant.2720    if (BestIdx == -1 && Idx > 0) {2721      assert(Tok.is(tok::annot_pragma_openmp_end) &&2722             "Expecting the end of the pragma here");2723      ConsumeAnnotationToken();2724      return StmtEmpty();2725    }2726    break;2727  }2728  case OMPD_threadprivate: {2729    // FIXME: Should this be permitted in C++?2730    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==2731        ParsedStmtContext()) {2732      Diag(Tok, diag::err_omp_immediate_directive)2733          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;2734    }2735    ConsumeToken();2736    DeclDirectiveListParserHelper Helper(this, DKind);2737    if (!ParseOpenMPSimpleVarList(DKind, Helper,2738                                  /*AllowScopeSpecifier=*/false)) {2739      skipUntilPragmaOpenMPEnd(DKind);2740      DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(2741          Loc, Helper.getIdentifiers());2742      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());2743    }2744    SkipUntil(tok::annot_pragma_openmp_end);2745    break;2746  }2747  case OMPD_groupprivate: {2748    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==2749        ParsedStmtContext()) {2750      Diag(Tok, diag::err_omp_immediate_directive)2751          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;2752    }2753    ConsumeToken();2754    DeclDirectiveListParserHelper Helper(this, DKind);2755    if (!ParseOpenMPSimpleVarList(DKind, Helper,2756                                  /*AllowScopeSpecifier=*/false)) {2757      skipUntilPragmaOpenMPEnd(DKind);2758      DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(2759          Loc, Helper.getIdentifiers());2760      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());2761    }2762    SkipUntil(tok::annot_pragma_openmp_end);2763    break;2764  }2765  case OMPD_allocate: {2766    // FIXME: Should this be permitted in C++?2767    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==2768        ParsedStmtContext()) {2769      Diag(Tok, diag::err_omp_immediate_directive)2770          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;2771    }2772    ConsumeToken();2773    DeclDirectiveListParserHelper Helper(this, DKind);2774    if (!ParseOpenMPSimpleVarList(DKind, Helper,2775                                  /*AllowScopeSpecifier=*/false)) {2776      SmallVector<OMPClause *, 1> Clauses;2777      if (Tok.isNot(tok::annot_pragma_openmp_end)) {2778        llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);2779        while (Tok.isNot(tok::annot_pragma_openmp_end)) {2780          OpenMPClauseKind CKind =2781              Tok.isAnnotation() ? OMPC_unknown2782                                 : getOpenMPClauseKind(PP.getSpelling(Tok));2783          Actions.OpenMP().StartOpenMPClause(CKind);2784          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,2785                                                !SeenClauses[unsigned(CKind)]);2786          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,2787                    StopBeforeMatch);2788          SeenClauses[unsigned(CKind)] = true;2789          if (Clause != nullptr)2790            Clauses.push_back(Clause);2791          if (Tok.is(tok::annot_pragma_openmp_end)) {2792            Actions.OpenMP().EndOpenMPClause();2793            break;2794          }2795          // Skip ',' if any.2796          if (Tok.is(tok::comma))2797            ConsumeToken();2798          Actions.OpenMP().EndOpenMPClause();2799        }2800        skipUntilPragmaOpenMPEnd(DKind);2801      }2802      DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(2803          Loc, Helper.getIdentifiers(), Clauses);2804      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());2805    }2806    SkipUntil(tok::annot_pragma_openmp_end);2807    break;2808  }2809  case OMPD_declare_reduction:2810    ConsumeToken();2811    if (DeclGroupPtrTy Res =2812            ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {2813      skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);2814      ConsumeAnyToken();2815      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());2816    } else {2817      SkipUntil(tok::annot_pragma_openmp_end);2818    }2819    break;2820  case OMPD_declare_mapper: {2821    ConsumeToken();2822    if (DeclGroupPtrTy Res =2823            ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {2824      // Skip the last annot_pragma_openmp_end.2825      ConsumeAnnotationToken();2826      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());2827    } else {2828      SkipUntil(tok::annot_pragma_openmp_end);2829    }2830    break;2831  }2832  case OMPD_declare_target: {2833    SourceLocation DTLoc = ConsumeAnyToken();2834    bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);2835    SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);2836    if (HasClauses)2837      ParseOMPDeclareTargetClauses(DTCI);2838    bool HasImplicitMappings =2839        !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);2840 2841    if (HasImplicitMappings) {2842      Diag(Tok, diag::err_omp_unexpected_directive)2843          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);2844      SkipUntil(tok::annot_pragma_openmp_end);2845      break;2846    }2847 2848    // Skip the last annot_pragma_openmp_end.2849    ConsumeAnyToken();2850 2851    Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);2852    break;2853  }2854  case OMPD_begin_declare_variant: {2855    ConsumeToken();2856    if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {2857      // Skip the last annot_pragma_openmp_end.2858      if (!isEofOrEom())2859        ConsumeAnnotationToken();2860    }2861    return Directive;2862  }2863  case OMPD_end_declare_variant: {2864    ConsumeToken();2865    if (Actions.OpenMP().isInOpenMPDeclareVariantScope())2866      Actions.OpenMP().ActOnOpenMPEndDeclareVariant();2867    else2868      Diag(Loc, diag::err_expected_begin_declare_variant);2869    ConsumeAnnotationToken();2870    break;2871  }2872  case OMPD_declare_simd:2873  case OMPD_begin_declare_target:2874  case OMPD_end_declare_target:2875  case OMPD_requires:2876  case OMPD_declare_variant:2877    Diag(Tok, diag::err_omp_unexpected_directive)2878        << 1 << getOpenMPDirectiveName(DKind, OMPVersion);2879    SkipUntil(tok::annot_pragma_openmp_end);2880    break;2881  case OMPD_assume: {2882    ConsumeToken();2883    Directive = ParseOpenMPInformationalDirective(2884        StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);2885    assert(!Directive.isUnset() &&2886           "Informational directive remains unprocessed");2887    return Directive;2888  }2889  case OMPD_unknown:2890  default:2891    Diag(Tok, diag::err_omp_unknown_directive);2892    SkipUntil(tok::annot_pragma_openmp_end);2893    break;2894  }2895  return Directive;2896}2897 2898bool Parser::ParseOpenMPSimpleVarList(2899    OpenMPDirectiveKind Kind,2900    const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>2901        &Callback,2902    bool AllowScopeSpecifier) {2903  unsigned OMPVersion = Actions.getLangOpts().OpenMP;2904  // Parse '('.2905  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);2906  if (T.expectAndConsume(diag::err_expected_lparen_after,2907                         getOpenMPDirectiveName(Kind, OMPVersion).data()))2908    return true;2909  bool IsCorrect = true;2910  bool NoIdentIsFound = true;2911 2912  // Read tokens while ')' or annot_pragma_openmp_end is not found.2913  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {2914    CXXScopeSpec SS;2915    UnqualifiedId Name;2916    // Read var name.2917    Token PrevTok = Tok;2918    NoIdentIsFound = false;2919 2920    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&2921        ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,2922                                       /*ObjectHasErrors=*/false, false)) {2923      IsCorrect = false;2924      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,2925                StopBeforeMatch);2926    } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,2927                                  /*ObjectHadErrors=*/false, false, false,2928                                  false, false, nullptr, Name)) {2929      IsCorrect = false;2930      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,2931                StopBeforeMatch);2932    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&2933               Tok.isNot(tok::annot_pragma_openmp_end)) {2934      IsCorrect = false;2935      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,2936                StopBeforeMatch);2937      Diag(PrevTok.getLocation(), diag::err_expected)2938          << tok::identifier2939          << SourceRange(PrevTok.getLocation(), PrevTokLocation);2940    } else {2941      Callback(SS, Actions.GetNameFromUnqualifiedId(Name));2942    }2943    // Consume ','.2944    if (Tok.is(tok::comma)) {2945      ConsumeToken();2946    }2947  }2948 2949  if (NoIdentIsFound) {2950    Diag(Tok, diag::err_expected) << tok::identifier;2951    IsCorrect = false;2952  }2953 2954  // Parse ')'.2955  IsCorrect = !T.consumeClose() && IsCorrect;2956 2957  return !IsCorrect;2958}2959 2960OMPClause *Parser::ParseOpenMPSizesClause() {2961  SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;2962  SmallVector<Expr *, 4> ValExprs;2963  if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,2964                                ValExprs))2965    return nullptr;2966 2967  return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,2968                                                 OpenLoc, CloseLoc);2969}2970 2971OMPClause *Parser::ParseOpenMPLoopRangeClause() {2972  SourceLocation ClauseNameLoc = ConsumeToken();2973  SourceLocation FirstLoc, CountLoc;2974 2975  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);2976  if (T.consumeOpen()) {2977    Diag(Tok, diag::err_expected) << tok::l_paren;2978    return nullptr;2979  }2980 2981  FirstLoc = Tok.getLocation();2982  ExprResult FirstVal = ParseConstantExpression();2983  if (!FirstVal.isUsable()) {2984    T.skipToEnd();2985    return nullptr;2986  }2987 2988  ExpectAndConsume(tok::comma);2989 2990  CountLoc = Tok.getLocation();2991  ExprResult CountVal = ParseConstantExpression();2992  if (!CountVal.isUsable()) {2993    T.skipToEnd();2994    return nullptr;2995  }2996 2997  T.consumeClose();2998 2999  return Actions.OpenMP().ActOnOpenMPLoopRangeClause(3000      FirstVal.get(), CountVal.get(), ClauseNameLoc, T.getOpenLocation(),3001      FirstLoc, CountLoc, T.getCloseLocation());3002}3003 3004OMPClause *Parser::ParseOpenMPPermutationClause() {3005  SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;3006  SmallVector<Expr *> ArgExprs;3007  if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,3008                                CloseLoc, ArgExprs,3009                                /*ReqIntConst=*/true))3010    return nullptr;3011 3012  return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,3013                                                       OpenLoc, CloseLoc);3014}3015 3016OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {3017  SourceLocation Loc = Tok.getLocation();3018  ConsumeAnyToken();3019 3020  // Parse '('.3021  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);3022  if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))3023    return nullptr;3024  SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;3025  do {3026    // Parse 'traits(expr) : Allocator' for >=5.23027    if (getLangOpts().OpenMP >= 52 && Tok.is(tok::identifier) &&3028        Tok.getIdentifierInfo()->getName() == "traits") {3029 3030      SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();3031 3032      ConsumeToken();3033 3034      // Parse '(' <expr> ')'3035      BalancedDelimiterTracker TraitParens(*this, tok::l_paren,3036                                           tok::annot_pragma_openmp_end);3037      TraitParens.consumeOpen();3038      ExprResult AllocatorTraits =3039          getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();3040      TraitParens.consumeClose();3041 3042      if (AllocatorTraits.isInvalid()) {3043        SkipUntil(3044            {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},3045            StopBeforeMatch);3046        break;3047      }3048 3049      // Expect ':'3050      if (Tok.isNot(tok::colon)) {3051        Diag(Tok, diag::err_expected) << tok::colon;3052        SkipUntil(3053            {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},3054            StopBeforeMatch);3055        continue;3056      }3057      ConsumeToken();3058 3059      CXXScopeSpec SS;3060      Token Replacement;3061      ExprResult AllocatorExpr =3062          getLangOpts().CPlusPlus3063              ? ParseCXXIdExpression()3064              : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,3065                                        Replacement);3066 3067      if (AllocatorExpr.isInvalid()) {3068        SkipUntil(3069            {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},3070            StopBeforeMatch);3071        break;3072      }3073 3074      D.Allocator = AllocatorExpr.get();3075      D.AllocatorTraits = AllocatorTraits.get();3076      D.LParenLoc = TraitParens.getOpenLocation();3077      D.RParenLoc = TraitParens.getCloseLocation();3078 3079      // Separator handling(;)3080      if (Tok.is(tok::comma)) {3081        // In 5.2, comma is invalid3082        Diag(Tok.getLocation(), diag::err_omp_allocator_comma_separator)3083            << FixItHint::CreateReplacement(Tok.getLocation(), ";");3084        ConsumeAnyToken();3085      } else if (Tok.is(tok::semi)) {3086        ConsumeAnyToken(); // valid separator3087      }3088 3089      continue;3090    }3091 3092    // Parse 'Allocator(expr)' for <5.23093    CXXScopeSpec SS;3094    Token Replacement;3095    ExprResult Allocator =3096        getLangOpts().CPlusPlus3097            ? ParseCXXIdExpression()3098            : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,3099                                      Replacement);3100    if (Allocator.isInvalid()) {3101      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,3102                StopBeforeMatch);3103      break;3104    }3105    SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();3106    D.Allocator = Allocator.get();3107    if (Tok.is(tok::l_paren)) {3108      BalancedDelimiterTracker T(*this, tok::l_paren,3109                                 tok::annot_pragma_openmp_end);3110      T.consumeOpen();3111      ExprResult AllocatorTraits =3112          getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();3113      T.consumeClose();3114      if (AllocatorTraits.isInvalid()) {3115        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,3116                  StopBeforeMatch);3117        break;3118      }3119      D.AllocatorTraits = AllocatorTraits.get();3120      D.LParenLoc = T.getOpenLocation();3121      D.RParenLoc = T.getCloseLocation();3122 3123      // Deprecation diagnostic in >= 5.23124      if (getLangOpts().OpenMP >= 52) {3125        Diag(Loc, diag::err_omp_deprecate_old_syntax)3126            << "allocator(expr)"      // %0: old form3127            << "uses_allocators"      // %1: clause name3128            << "traits(expr): alloc"; // %2: suggested new form3129      }3130    }3131    if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))3132      Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;3133    // Parse ','3134    if (Tok.is(tok::comma))3135      ConsumeAnyToken();3136  } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));3137  T.consumeClose();3138  return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(3139      Loc, T.getOpenLocation(), T.getCloseLocation(), Data);3140}3141 3142OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,3143                                     OpenMPClauseKind CKind, bool FirstClause) {3144  OMPClauseKind = CKind;3145  OMPClause *Clause = nullptr;3146  bool ErrorFound = false;3147  bool WrongDirective = false;3148  unsigned OMPVersion = Actions.getLangOpts().OpenMP;3149 3150  // Check if clause is allowed for the given directive.3151  if (CKind != OMPC_unknown &&3152      !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {3153    Diag(Tok, diag::err_omp_unexpected_clause)3154        << getOpenMPClauseName(CKind)3155        << getOpenMPDirectiveName(DKind, OMPVersion);3156    ErrorFound = true;3157    WrongDirective = true;3158  }3159 3160  switch (CKind) {3161  case OMPC_final:3162  case OMPC_num_threads:3163  case OMPC_safelen:3164  case OMPC_simdlen:3165  case OMPC_collapse:3166  case OMPC_ordered:3167  case OMPC_priority:3168  case OMPC_grainsize:3169  case OMPC_num_tasks:3170  case OMPC_hint:3171  case OMPC_allocator:3172  case OMPC_depobj:3173  case OMPC_detach:3174  case OMPC_novariants:3175  case OMPC_nocontext:3176  case OMPC_filter:3177  case OMPC_partial:3178  case OMPC_align:3179  case OMPC_message:3180  case OMPC_ompx_dyn_cgroup_mem:3181  case OMPC_dyn_groupprivate:3182    // OpenMP [2.5, Restrictions]3183    //  At most one num_threads clause can appear on the directive.3184    // OpenMP [2.8.1, simd construct, Restrictions]3185    //  Only one safelen  clause can appear on a simd directive.3186    //  Only one simdlen  clause can appear on a simd directive.3187    //  Only one collapse clause can appear on a simd directive.3188    // OpenMP [2.11.1, task Construct, Restrictions]3189    //  At most one if clause can appear on the directive.3190    //  At most one final clause can appear on the directive.3191    // OpenMP [teams Construct, Restrictions]3192    //  At most one num_teams clause can appear on the directive.3193    //  At most one thread_limit clause can appear on the directive.3194    // OpenMP [2.9.1, task Construct, Restrictions]3195    // At most one priority clause can appear on the directive.3196    // OpenMP [2.9.2, taskloop Construct, Restrictions]3197    // At most one grainsize clause can appear on the directive.3198    // OpenMP [2.9.2, taskloop Construct, Restrictions]3199    // At most one num_tasks clause can appear on the directive.3200    // OpenMP [2.11.3, allocate Directive, Restrictions]3201    // At most one allocator clause can appear on the directive.3202    // OpenMP 5.0, 2.10.1 task Construct, Restrictions.3203    // At most one detach clause can appear on the directive.3204    // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.3205    // At most one novariants clause can appear on a dispatch directive.3206    // At most one nocontext clause can appear on a dispatch directive.3207    // OpenMP [5.1, error directive, Restrictions]3208    // At most one message clause can appear on the directive3209    if (!FirstClause) {3210      Diag(Tok, diag::err_omp_more_one_clause)3211          << getOpenMPDirectiveName(DKind, OMPVersion)3212          << getOpenMPClauseName(CKind) << 0;3213      ErrorFound = true;3214    }3215 3216    if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&3217        PP.LookAhead(/*N=*/0).isNot(tok::l_paren))3218      Clause = ParseOpenMPClause(CKind, WrongDirective);3219    else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||3220             CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)3221      Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);3222    else3223      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);3224    break;3225  case OMPC_threadset:3226  case OMPC_fail:3227  case OMPC_proc_bind:3228  case OMPC_atomic_default_mem_order:3229  case OMPC_at:3230  case OMPC_severity:3231  case OMPC_bind:3232    // OpenMP [2.14.3.1, Restrictions]3233    //  Only a single default clause may be specified on a parallel, task or3234    //  teams directive.3235    // OpenMP [2.5, parallel Construct, Restrictions]3236    //  At most one proc_bind clause can appear on the directive.3237    // OpenMP [5.0, Requires directive, Restrictions]3238    //  At most one atomic_default_mem_order clause can appear3239    //  on the directive3240    // OpenMP [5.1, error directive, Restrictions]3241    //  At most one at clause can appear on the directive3242    //  At most one severity clause can appear on the directive3243    // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.3244    // At most one bind clause can appear on a loop directive.3245    if (!FirstClause) {3246      Diag(Tok, diag::err_omp_more_one_clause)3247          << getOpenMPDirectiveName(DKind, OMPVersion)3248          << getOpenMPClauseName(CKind) << 0;3249      ErrorFound = true;3250    }3251 3252    Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);3253    break;3254  case OMPC_device:3255  case OMPC_schedule:3256  case OMPC_dist_schedule:3257  case OMPC_defaultmap:3258  case OMPC_default:3259  case OMPC_order:3260    // OpenMP [2.7.1, Restrictions, p. 3]3261    //  Only one schedule clause can appear on a loop directive.3262    // OpenMP 4.5 [2.10.4, Restrictions, p. 106]3263    //  At most one defaultmap clause can appear on the directive.3264    // OpenMP 5.0 [2.12.5, target construct, Restrictions]3265    //  At most one device clause can appear on the directive.3266    // OpenMP 5.1 [2.11.3, order clause, Restrictions]3267    //  At most one order clause may appear on a construct.3268    if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&3269        (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {3270      Diag(Tok, diag::err_omp_more_one_clause)3271          << getOpenMPDirectiveName(DKind, OMPVersion)3272          << getOpenMPClauseName(CKind) << 0;3273      ErrorFound = true;3274    }3275    [[fallthrough]];3276  case OMPC_if:3277    Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);3278    break;3279  case OMPC_holds:3280    Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);3281    break;3282  case OMPC_nowait:3283  case OMPC_untied:3284  case OMPC_mergeable:3285  case OMPC_read:3286  case OMPC_write:3287  case OMPC_capture:3288  case OMPC_compare:3289  case OMPC_seq_cst:3290  case OMPC_acq_rel:3291  case OMPC_acquire:3292  case OMPC_release:3293  case OMPC_relaxed:3294  case OMPC_weak:3295  case OMPC_threads:3296  case OMPC_simd:3297  case OMPC_nogroup:3298  case OMPC_unified_address:3299  case OMPC_unified_shared_memory:3300  case OMPC_reverse_offload:3301  case OMPC_dynamic_allocators:3302  case OMPC_full:3303    // OpenMP [2.7.1, Restrictions, p. 9]3304    //  Only one ordered clause can appear on a loop directive.3305    // OpenMP [2.7.1, Restrictions, C/C++, p. 4]3306    //  Only one nowait clause can appear on a for directive.3307    // OpenMP [5.0, Requires directive, Restrictions]3308    //   Each of the requires clauses can appear at most once on the directive.3309    if (!FirstClause) {3310      Diag(Tok, diag::err_omp_more_one_clause)3311          << getOpenMPDirectiveName(DKind, OMPVersion)3312          << getOpenMPClauseName(CKind) << 0;3313      ErrorFound = true;3314    }3315 3316    if (CKind == OMPC_nowait && PP.LookAhead(/*N=*/0).is(tok::l_paren) &&3317        getLangOpts().OpenMP >= 60)3318      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);3319    else3320      Clause = ParseOpenMPClause(CKind, WrongDirective);3321    break;3322  case OMPC_self_maps:3323    // OpenMP [6.0, self_maps clause]3324    if (getLangOpts().OpenMP < 60) {3325      Diag(Tok, diag::err_omp_expected_clause)3326          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);3327      ErrorFound = true;3328    }3329    if (!FirstClause) {3330      Diag(Tok, diag::err_omp_more_one_clause)3331          << getOpenMPDirectiveName(DKind, OMPVersion)3332          << getOpenMPClauseName(CKind) << 0;3333      ErrorFound = true;3334    }3335    Clause = ParseOpenMPClause(CKind, WrongDirective);3336    break;3337  case OMPC_update:3338    if (!FirstClause) {3339      Diag(Tok, diag::err_omp_more_one_clause)3340          << getOpenMPDirectiveName(DKind, OMPVersion)3341          << getOpenMPClauseName(CKind) << 0;3342      ErrorFound = true;3343    }3344 3345    Clause = (DKind == OMPD_depobj)3346                 ? ParseOpenMPSimpleClause(CKind, WrongDirective)3347                 : ParseOpenMPClause(CKind, WrongDirective);3348    break;3349  case OMPC_num_teams:3350  case OMPC_thread_limit:3351    if (!FirstClause) {3352      Diag(Tok, diag::err_omp_more_one_clause)3353          << getOpenMPDirectiveName(DKind, OMPVersion)3354          << getOpenMPClauseName(CKind) << 0;3355      ErrorFound = true;3356    }3357    [[fallthrough]];3358  case OMPC_private:3359  case OMPC_firstprivate:3360  case OMPC_lastprivate:3361  case OMPC_shared:3362  case OMPC_reduction:3363  case OMPC_task_reduction:3364  case OMPC_in_reduction:3365  case OMPC_linear:3366  case OMPC_aligned:3367  case OMPC_copyin:3368  case OMPC_copyprivate:3369  case OMPC_flush:3370  case OMPC_depend:3371  case OMPC_map:3372  case OMPC_to:3373  case OMPC_from:3374  case OMPC_use_device_ptr:3375  case OMPC_use_device_addr:3376  case OMPC_is_device_ptr:3377  case OMPC_has_device_addr:3378  case OMPC_allocate:3379  case OMPC_nontemporal:3380  case OMPC_inclusive:3381  case OMPC_exclusive:3382  case OMPC_affinity:3383  case OMPC_doacross:3384  case OMPC_enter:3385    if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&3386        CKind == OMPC_depend)3387      Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);3388    Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);3389    break;3390  case OMPC_sizes:3391    if (!FirstClause) {3392      Diag(Tok, diag::err_omp_more_one_clause)3393          << getOpenMPDirectiveName(DKind, OMPVersion)3394          << getOpenMPClauseName(CKind) << 0;3395      ErrorFound = true;3396    }3397 3398    Clause = ParseOpenMPSizesClause();3399    break;3400  case OMPC_permutation:3401    if (!FirstClause) {3402      Diag(Tok, diag::err_omp_more_one_clause)3403          << getOpenMPDirectiveName(DKind, OMPVersion)3404          << getOpenMPClauseName(CKind) << 0;3405      ErrorFound = true;3406    }3407    Clause = ParseOpenMPPermutationClause();3408    break;3409  case OMPC_uses_allocators:3410    Clause = ParseOpenMPUsesAllocatorClause(DKind);3411    break;3412  case OMPC_destroy:3413    if (DKind != OMPD_interop) {3414      if (!FirstClause) {3415        Diag(Tok, diag::err_omp_more_one_clause)3416            << getOpenMPDirectiveName(DKind, OMPVersion)3417            << getOpenMPClauseName(CKind) << 0;3418        ErrorFound = true;3419      }3420      Clause = ParseOpenMPClause(CKind, WrongDirective);3421      break;3422    }3423    [[fallthrough]];3424  case OMPC_init:3425  case OMPC_use:3426    Clause = ParseOpenMPInteropClause(CKind, WrongDirective);3427    break;3428  case OMPC_device_type:3429  case OMPC_unknown:3430    skipUntilPragmaOpenMPEnd(DKind);3431    break;3432  case OMPC_threadprivate:3433  case OMPC_groupprivate:3434  case OMPC_uniform:3435  case OMPC_match:3436    if (!WrongDirective)3437      Diag(Tok, diag::err_omp_unexpected_clause)3438          << getOpenMPClauseName(CKind)3439          << getOpenMPDirectiveName(DKind, OMPVersion);3440    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);3441    break;3442  case OMPC_absent:3443  case OMPC_contains: {3444    SourceLocation Loc = ConsumeToken();3445    SourceLocation LLoc = Tok.getLocation();3446    SourceLocation RLoc;3447    llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;3448    BalancedDelimiterTracker T(*this, tok::l_paren);3449    T.consumeOpen();3450    do {3451      OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));3452      if (DK == OMPD_unknown) {3453        skipUntilPragmaOpenMPEnd(OMPD_assume);3454        Diag(Tok, diag::err_omp_unexpected_clause)3455            << getOpenMPClauseName(CKind)3456            << getOpenMPDirectiveName(DKind, OMPVersion);3457        break;3458      }3459      if (isOpenMPExecutableDirective(DK)) {3460        DKVec.push_back(DK);3461        ConsumeToken();3462      } else {3463        Diag(Tok, diag::err_omp_unexpected_clause)3464            << getOpenMPClauseName(CKind)3465            << getOpenMPDirectiveName(DKind, OMPVersion);3466      }3467    } while (TryConsumeToken(tok::comma));3468    RLoc = Tok.getLocation();3469    T.consumeClose();3470    Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(3471        CKind, DKVec, Loc, LLoc, RLoc);3472    break;3473  }3474  case OMPC_no_openmp:3475  case OMPC_no_openmp_routines:3476  case OMPC_no_openmp_constructs:3477  case OMPC_no_parallelism: {3478    if (!FirstClause) {3479      Diag(Tok, diag::err_omp_more_one_clause)3480          << getOpenMPDirectiveName(DKind, OMPVersion)3481          << getOpenMPClauseName(CKind) << 0;3482      ErrorFound = true;3483    }3484    SourceLocation Loc = ConsumeToken();3485    Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(3486        CKind, Loc, Tok.getLocation());3487    break;3488  }3489  case OMPC_ompx_attribute:3490    Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);3491    break;3492  case OMPC_ompx_bare:3493    if (DKind == llvm::omp::Directive::OMPD_target) {3494      // Flang splits the combined directives which requires OMPD_target to be3495      // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need3496      // to explicitly check whether this clause is applied to an `omp target`3497      // without `teams` and emit an error.3498      Diag(Tok, diag::err_omp_unexpected_clause)3499          << getOpenMPClauseName(CKind)3500          << getOpenMPDirectiveName(DKind, OMPVersion);3501      ErrorFound = true;3502      WrongDirective = true;3503    }3504    if (WrongDirective)3505      Diag(Tok, diag::note_ompx_bare_clause)3506          << getOpenMPClauseName(CKind) << "target teams";3507    if (!ErrorFound && !getLangOpts().OpenMPExtensions) {3508      Diag(Tok, diag::err_omp_unexpected_clause_extension_only)3509          << getOpenMPClauseName(CKind)3510          << getOpenMPDirectiveName(DKind, OMPVersion);3511      ErrorFound = true;3512    }3513    Clause = ParseOpenMPClause(CKind, WrongDirective);3514    break;3515  case OMPC_looprange:3516    Clause = ParseOpenMPLoopRangeClause();3517    break;3518  default:3519    break;3520  }3521  return ErrorFound ? nullptr : Clause;3522}3523 3524/// Parses simple expression in parens for single-expression clauses of OpenMP3525/// constructs.3526/// \param RLoc Returned location of right paren.3527ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,3528                                         SourceLocation &RLoc,3529                                         bool IsAddressOfOperand) {3530  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);3531  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))3532    return ExprError();3533 3534  SourceLocation ELoc = Tok.getLocation();3535  ExprResult LHS(3536      ParseCastExpression(CastParseKind::AnyCastExpr, IsAddressOfOperand,3537                          TypoCorrectionTypeBehavior::AllowNonTypes));3538  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));3539  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);3540 3541  // Parse ')'.3542  RLoc = Tok.getLocation();3543  if (!T.consumeClose())3544    RLoc = T.getCloseLocation();3545 3546  return Val;3547}3548 3549OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,3550                                               bool ParseOnly) {3551  SourceLocation Loc = ConsumeToken();3552  SourceLocation LLoc = Tok.getLocation();3553  SourceLocation RLoc;3554 3555  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);3556 3557  if (Val.isInvalid())3558    return nullptr;3559 3560  if (ParseOnly)3561    return nullptr;3562  return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,3563                                                      LLoc, RLoc);3564}3565 3566bool Parser::ParseOpenMPIndirectClause(3567    SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {3568  SourceLocation Loc = ConsumeToken();3569  SourceLocation RLoc;3570 3571  if (Tok.isNot(tok::l_paren)) {3572    if (ParseOnly)3573      return false;3574    DTCI.Indirect = nullptr;3575    return true;3576  }3577 3578  ExprResult Val =3579      ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);3580  if (Val.isInvalid())3581    return false;3582 3583  if (ParseOnly)3584    return false;3585 3586  if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&3587      !Val.get()->isInstantiationDependent() &&3588      !Val.get()->containsUnexpandedParameterPack()) {3589    ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());3590    if (Ret.isInvalid())3591      return false;3592    llvm::APSInt Result;3593    Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,3594                                                  AllowFoldKind::Allow);3595    if (Ret.isInvalid())3596      return false;3597    DTCI.Indirect = Val.get();3598    return true;3599  }3600  return false;3601}3602 3603bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,3604                                 OpenMPClauseKind Kind) {3605  const Token &Tok = getCurToken();3606  bool HasError = false;3607  bool IsTarget = false;3608  bool IsTargetSync = false;3609 3610  while (Tok.is(tok::identifier)) {3611    // Currently prefer_type is only allowed with 'init' and it must be first.3612    bool PreferTypeAllowed = Kind == OMPC_init &&3613                             InteropInfo.PreferTypes.empty() && !IsTarget &&3614                             !IsTargetSync;3615    if (Tok.getIdentifierInfo()->isStr("target")) {3616      // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]3617      // Each interop-type may be specified on an action-clause at most3618      // once.3619      if (IsTarget)3620        Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";3621      IsTarget = true;3622      ConsumeToken();3623    } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {3624      if (IsTargetSync)3625        Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";3626      IsTargetSync = true;3627      ConsumeToken();3628    } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&3629               PreferTypeAllowed) {3630      ConsumeToken();3631      BalancedDelimiterTracker PT(*this, tok::l_paren,3632                                  tok::annot_pragma_openmp_end);3633      if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))3634        HasError = true;3635 3636      while (Tok.isNot(tok::r_paren)) {3637        SourceLocation Loc = Tok.getLocation();3638        ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);3639        ExprResult PTExpr = ParseRHSOfBinaryExpression(LHS, prec::Conditional);3640        PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,3641                                             /*DiscardedValue=*/false);3642        if (PTExpr.isUsable()) {3643          InteropInfo.PreferTypes.push_back(PTExpr.get());3644        } else {3645          HasError = true;3646          SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,3647                    StopBeforeMatch);3648        }3649 3650        if (Tok.is(tok::comma))3651          ConsumeToken();3652      }3653      PT.consumeClose();3654    } else {3655      HasError = true;3656      Diag(Tok, diag::err_omp_expected_interop_type);3657      ConsumeToken();3658    }3659    if (!Tok.is(tok::comma))3660      break;3661    ConsumeToken();3662  }3663 3664  if (!HasError && !IsTarget && !IsTargetSync) {3665    Diag(Tok, diag::err_omp_expected_interop_type);3666    HasError = true;3667  }3668 3669  if (Kind == OMPC_init) {3670    if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))3671      Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";3672    if (Tok.is(tok::colon))3673      ConsumeToken();3674  }3675 3676  // As of OpenMP 5.1,there are two interop-types, "target" and3677  // "targetsync". Either or both are allowed for a single interop.3678  InteropInfo.IsTarget = IsTarget;3679  InteropInfo.IsTargetSync = IsTargetSync;3680 3681  return HasError;3682}3683 3684OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,3685                                            bool ParseOnly) {3686  SourceLocation Loc = ConsumeToken();3687  // Parse '('.3688  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);3689  if (T.expectAndConsume(diag::err_expected_lparen_after,3690                         getOpenMPClauseName(Kind).data()))3691    return nullptr;3692 3693  bool InteropError = false;3694  OMPInteropInfo InteropInfo;3695  if (Kind == OMPC_init)3696    InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);3697 3698  // Parse the variable.3699  SourceLocation VarLoc = Tok.getLocation();3700  ExprResult InteropVarExpr = ParseAssignmentExpression();3701  if (!InteropVarExpr.isUsable()) {3702    SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,3703              StopBeforeMatch);3704  }3705 3706  // Parse ')'.3707  SourceLocation RLoc = Tok.getLocation();3708  if (!T.consumeClose())3709    RLoc = T.getCloseLocation();3710 3711  if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)3712    return nullptr;3713 3714  if (Kind == OMPC_init)3715    return Actions.OpenMP().ActOnOpenMPInitClause(3716        InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,3717        RLoc);3718  if (Kind == OMPC_use)3719    return Actions.OpenMP().ActOnOpenMPUseClause(3720        InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);3721 3722  if (Kind == OMPC_destroy)3723    return Actions.OpenMP().ActOnOpenMPDestroyClause(3724        InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);3725 3726  llvm_unreachable("Unexpected interop variable clause.");3727}3728 3729OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {3730  SourceLocation Loc = ConsumeToken();3731  // Parse '('.3732  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);3733  if (T.expectAndConsume(diag::err_expected_lparen_after,3734                         getOpenMPClauseName(OMPC_ompx_attribute).data()))3735    return nullptr;3736 3737  ParsedAttributes ParsedAttrs(AttrFactory);3738  ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);3739 3740  // Parse ')'.3741  if (T.consumeClose())3742    return nullptr;3743 3744  if (ParseOnly)3745    return nullptr;3746 3747  SmallVector<Attr *> Attrs;3748  for (const ParsedAttr &PA : ParsedAttrs) {3749    switch (PA.getKind()) {3750    case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:3751      if (!PA.checkExactlyNumArgs(Actions, 2))3752        continue;3753      if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(3754              PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))3755        Attrs.push_back(A);3756      continue;3757    case ParsedAttr::AT_AMDGPUWavesPerEU:3758      if (!PA.checkAtLeastNumArgs(Actions, 1) ||3759          !PA.checkAtMostNumArgs(Actions, 2))3760        continue;3761      if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(3762              PA, PA.getArgAsExpr(0),3763              PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))3764        Attrs.push_back(A);3765      continue;3766    case ParsedAttr::AT_CUDALaunchBounds:3767      if (!PA.checkAtLeastNumArgs(Actions, 1) ||3768          !PA.checkAtMostNumArgs(Actions, 2))3769        continue;3770      if (auto *A = Actions.CreateLaunchBoundsAttr(3771              PA, PA.getArgAsExpr(0),3772              PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,3773              PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))3774        Attrs.push_back(A);3775      continue;3776    default:3777      Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;3778      continue;3779    };3780  }3781 3782  return Actions.OpenMP().ActOnOpenMPXAttributeClause(3783      Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());3784}3785 3786OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,3787                                           bool ParseOnly) {3788  std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);3789  if (!Val || ParseOnly)3790    return nullptr;3791  if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&3792      (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||3793       static_cast<DefaultKind>(Val->Type) ==3794           OMP_DEFAULT_firstprivate)) {3795    Diag(Val->LOpen, diag::err_omp_invalid_dsa)3796        << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==3797                                       OMP_DEFAULT_private3798                                   ? OMPC_private3799                                   : OMPC_firstprivate)3800        << getOpenMPClauseName(OMPC_default) << "5.1";3801    return nullptr;3802  }3803  return Actions.OpenMP().ActOnOpenMPSimpleClause(3804      Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);3805}3806 3807OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {3808  SourceLocation Loc = Tok.getLocation();3809  ConsumeAnyToken();3810 3811  if (ParseOnly)3812    return nullptr;3813  return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());3814}3815 3816OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,3817                                                      OpenMPClauseKind Kind,3818                                                      bool ParseOnly) {3819  SourceLocation Loc = ConsumeToken();3820  SourceLocation DelimLoc;3821  // Parse '('.3822  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);3823  if (T.expectAndConsume(diag::err_expected_lparen_after,3824                         getOpenMPClauseName(Kind).data()))3825    return nullptr;3826 3827  ExprResult Val;3828  SmallVector<unsigned, 4> Arg;3829  SmallVector<SourceLocation, 4> KLoc;3830  if (Kind == OMPC_schedule) {3831    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };3832    Arg.resize(NumberOfElements);3833    KLoc.resize(NumberOfElements);3834    Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;3835    Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;3836    Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;3837    unsigned KindModifier = getOpenMPSimpleClauseType(3838        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3839    if (KindModifier > OMPC_SCHEDULE_unknown) {3840      // Parse 'modifier'3841      Arg[Modifier1] = KindModifier;3842      KLoc[Modifier1] = Tok.getLocation();3843      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3844          Tok.isNot(tok::annot_pragma_openmp_end))3845        ConsumeAnyToken();3846      if (Tok.is(tok::comma)) {3847        // Parse ',' 'modifier'3848        ConsumeAnyToken();3849        KindModifier = getOpenMPSimpleClauseType(3850            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3851        Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown3852                             ? KindModifier3853                             : (unsigned)OMPC_SCHEDULE_unknown;3854        KLoc[Modifier2] = Tok.getLocation();3855        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3856            Tok.isNot(tok::annot_pragma_openmp_end))3857          ConsumeAnyToken();3858      }3859      // Parse ':'3860      if (Tok.is(tok::colon))3861        ConsumeAnyToken();3862      else3863        Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";3864      KindModifier = getOpenMPSimpleClauseType(3865          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3866    }3867    Arg[ScheduleKind] = KindModifier;3868    KLoc[ScheduleKind] = Tok.getLocation();3869    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3870        Tok.isNot(tok::annot_pragma_openmp_end))3871      ConsumeAnyToken();3872    if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||3873         Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||3874         Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&3875        Tok.is(tok::comma))3876      DelimLoc = ConsumeAnyToken();3877  } else if (Kind == OMPC_dist_schedule) {3878    Arg.push_back(getOpenMPSimpleClauseType(3879        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));3880    KLoc.push_back(Tok.getLocation());3881    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3882        Tok.isNot(tok::annot_pragma_openmp_end))3883      ConsumeAnyToken();3884    if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))3885      DelimLoc = ConsumeAnyToken();3886  } else if (Kind == OMPC_default) {3887    // Get a default modifier3888    unsigned Modifier = getOpenMPSimpleClauseType(3889        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3890 3891    Arg.push_back(Modifier);3892    KLoc.push_back(Tok.getLocation());3893    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3894        Tok.isNot(tok::annot_pragma_openmp_end))3895      ConsumeAnyToken();3896    // Parse ':'3897    if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {3898      ConsumeAnyToken();3899      // Get a variable-category attribute for default clause modifier3900      OpenMPDefaultClauseVariableCategory VariableCategory =3901          getOpenMPDefaultVariableCategory(3902              Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3903      Arg.push_back(VariableCategory);3904      KLoc.push_back(Tok.getLocation());3905      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3906          Tok.isNot(tok::annot_pragma_openmp_end))3907        ConsumeAnyToken();3908    } else {3909      Arg.push_back(OMPC_DEFAULT_VC_all);3910      KLoc.push_back(SourceLocation());3911    }3912  } else if (Kind == OMPC_defaultmap) {3913    // Get a defaultmap modifier3914    unsigned Modifier = getOpenMPSimpleClauseType(3915        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3916 3917    // Set defaultmap modifier to unknown if it is either scalar, aggregate, or3918    // pointer3919    if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)3920      Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;3921    Arg.push_back(Modifier);3922    KLoc.push_back(Tok.getLocation());3923    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3924        Tok.isNot(tok::annot_pragma_openmp_end))3925      ConsumeAnyToken();3926    // Parse ':'3927    if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {3928      if (Tok.is(tok::colon))3929        ConsumeAnyToken();3930      else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)3931        Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";3932      // Get a defaultmap kind3933      Arg.push_back(getOpenMPSimpleClauseType(3934          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));3935      KLoc.push_back(Tok.getLocation());3936      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3937          Tok.isNot(tok::annot_pragma_openmp_end))3938        ConsumeAnyToken();3939    } else {3940      Arg.push_back(OMPC_DEFAULTMAP_unknown);3941      KLoc.push_back(SourceLocation());3942    }3943  } else if (Kind == OMPC_order) {3944    enum { Modifier, OrderKind, NumberOfElements };3945    Arg.resize(NumberOfElements);3946    KLoc.resize(NumberOfElements);3947    Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;3948    Arg[OrderKind] = OMPC_ORDER_unknown;3949    unsigned KindModifier = getOpenMPSimpleClauseType(3950        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3951    if (KindModifier > OMPC_ORDER_unknown) {3952      // Parse 'modifier'3953      Arg[Modifier] = KindModifier;3954      KLoc[Modifier] = Tok.getLocation();3955      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3956          Tok.isNot(tok::annot_pragma_openmp_end))3957        ConsumeAnyToken();3958      // Parse ':'3959      if (Tok.is(tok::colon))3960        ConsumeAnyToken();3961      else3962        Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";3963      KindModifier = getOpenMPSimpleClauseType(3964          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());3965    }3966    Arg[OrderKind] = KindModifier;3967    KLoc[OrderKind] = Tok.getLocation();3968    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&3969        Tok.isNot(tok::annot_pragma_openmp_end))3970      ConsumeAnyToken();3971  } else if (Kind == OMPC_device) {3972    // Only target executable directives support extended device construct.3973    if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&3974        NextToken().is(tok::colon)) {3975      // Parse optional <device modifier> ':'3976      Arg.push_back(getOpenMPSimpleClauseType(3977          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));3978      KLoc.push_back(Tok.getLocation());3979      ConsumeAnyToken();3980      // Parse ':'3981      ConsumeAnyToken();3982    } else {3983      Arg.push_back(OMPC_DEVICE_unknown);3984      KLoc.emplace_back();3985    }3986  } else if (Kind == OMPC_grainsize) {3987    // Parse optional <grainsize modifier> ':'3988    OpenMPGrainsizeClauseModifier Modifier =3989        static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(3990            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),3991            getLangOpts()));3992    if (getLangOpts().OpenMP >= 51) {3993      if (NextToken().is(tok::colon)) {3994        Arg.push_back(Modifier);3995        KLoc.push_back(Tok.getLocation());3996        // Parse modifier3997        ConsumeAnyToken();3998        // Parse ':'3999        ConsumeAnyToken();4000      } else {4001        if (Modifier == OMPC_GRAINSIZE_strict) {4002          Diag(Tok, diag::err_modifier_expected_colon) << "strict";4003          // Parse modifier4004          ConsumeAnyToken();4005        }4006        Arg.push_back(OMPC_GRAINSIZE_unknown);4007        KLoc.emplace_back();4008      }4009    } else {4010      Arg.push_back(OMPC_GRAINSIZE_unknown);4011      KLoc.emplace_back();4012    }4013  } else if (Kind == OMPC_dyn_groupprivate) {4014    enum { SimpleModifier, ComplexModifier, NumberOfModifiers };4015    Arg.resize(NumberOfModifiers);4016    KLoc.resize(NumberOfModifiers);4017    Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;4018    Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;4019 4020    auto ConsumeModifier = [&]() {4021      unsigned Type = NumberOfModifiers;4022      unsigned Modifier;4023      SourceLocation Loc;4024      if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&4025          NextToken().is(tok::l_paren)) {4026        ConsumeToken();4027        BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);4028        ParenT.consumeOpen();4029 4030        Modifier = getOpenMPSimpleClauseType(4031            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());4032        if (Modifier <= OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown ||4033            Modifier >= OMPC_DYN_GROUPPRIVATE_FALLBACK_last) {4034          Diag(Tok.getLocation(), diag::err_expected)4035              << "'abort', 'null' or 'default_mem' in fallback modifier";4036          SkipUntil(tok::r_paren);4037          return std::make_tuple(Type, Modifier, Loc);4038        }4039        Type = ComplexModifier;4040        Loc = Tok.getLocation();4041        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&4042            Tok.isNot(tok::annot_pragma_openmp_end))4043          ConsumeAnyToken();4044        ParenT.consumeClose();4045      } else {4046        Modifier = getOpenMPSimpleClauseType(4047            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());4048        if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {4049          Type = SimpleModifier;4050          Loc = Tok.getLocation();4051          if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&4052              Tok.isNot(tok::annot_pragma_openmp_end))4053            ConsumeAnyToken();4054        }4055      }4056      return std::make_tuple(Type, Modifier, Loc);4057    };4058 4059    auto SaveModifier = [&](unsigned Type, unsigned Modifier,4060                            SourceLocation Loc) {4061      assert(Type < NumberOfModifiers && "Unexpected modifier type");4062      if (!KLoc[Type].isValid()) {4063        Arg[Type] = Modifier;4064        KLoc[Type] = Loc;4065      } else {4066        Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)4067            << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)4068            << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);4069      }4070    };4071 4072    // Parse 'modifier'4073    auto [Type1, Mod1, Loc1] = ConsumeModifier();4074    if (Type1 < NumberOfModifiers) {4075      SaveModifier(Type1, Mod1, Loc1);4076      if (Tok.is(tok::comma)) {4077        // Parse ',' 'modifier'4078        ConsumeAnyToken();4079        auto [Type2, Mod2, Loc2] = ConsumeModifier();4080        if (Type2 < NumberOfModifiers)4081          SaveModifier(Type2, Mod2, Loc2);4082      }4083      // Parse ':'4084      if (Tok.is(tok::colon))4085        ConsumeAnyToken();4086      else4087        Diag(Tok, diag::warn_pragma_expected_colon)4088            << "dyn_groupprivate modifier";4089    }4090  } else if (Kind == OMPC_num_tasks) {4091    // Parse optional <num_tasks modifier> ':'4092    OpenMPNumTasksClauseModifier Modifier =4093        static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(4094            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),4095            getLangOpts()));4096    if (getLangOpts().OpenMP >= 51) {4097      if (NextToken().is(tok::colon)) {4098        Arg.push_back(Modifier);4099        KLoc.push_back(Tok.getLocation());4100        // Parse modifier4101        ConsumeAnyToken();4102        // Parse ':'4103        ConsumeAnyToken();4104      } else {4105        if (Modifier == OMPC_NUMTASKS_strict) {4106          Diag(Tok, diag::err_modifier_expected_colon) << "strict";4107          // Parse modifier4108          ConsumeAnyToken();4109        }4110        Arg.push_back(OMPC_NUMTASKS_unknown);4111        KLoc.emplace_back();4112      }4113    } else {4114      Arg.push_back(OMPC_NUMTASKS_unknown);4115      KLoc.emplace_back();4116    }4117  } else if (Kind == OMPC_num_threads) {4118    // Parse optional <num_threads modifier> ':'4119    OpenMPNumThreadsClauseModifier Modifier =4120        static_cast<OpenMPNumThreadsClauseModifier>(getOpenMPSimpleClauseType(4121            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),4122            getLangOpts()));4123    if (getLangOpts().OpenMP >= 60) {4124      if (NextToken().is(tok::colon)) {4125        Arg.push_back(Modifier);4126        KLoc.push_back(Tok.getLocation());4127        // Parse modifier4128        ConsumeAnyToken();4129        // Parse ':'4130        ConsumeAnyToken();4131      } else {4132        if (Modifier == OMPC_NUMTHREADS_strict) {4133          Diag(Tok, diag::err_modifier_expected_colon) << "strict";4134          // Parse modifier4135          ConsumeAnyToken();4136        }4137        Arg.push_back(OMPC_NUMTHREADS_unknown);4138        KLoc.emplace_back();4139      }4140    } else {4141      Arg.push_back(OMPC_NUMTHREADS_unknown);4142      KLoc.emplace_back();4143    }4144  } else {4145    assert(Kind == OMPC_if);4146    KLoc.push_back(Tok.getLocation());4147    TentativeParsingAction TPA(*this);4148    auto DK = parseOpenMPDirectiveKind(*this);4149    Arg.push_back(static_cast<unsigned>(DK));4150    if (DK != OMPD_unknown) {4151      ConsumeToken();4152      if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {4153        TPA.Commit();4154        DelimLoc = ConsumeToken();4155      } else {4156        TPA.Revert();4157        Arg.back() = unsigned(OMPD_unknown);4158      }4159    } else {4160      TPA.Revert();4161    }4162  }4163 4164  bool NeedAnExpression =4165      (Kind == OMPC_schedule && DelimLoc.isValid()) ||4166      (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||4167      Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||4168      Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;4169  if (NeedAnExpression) {4170    SourceLocation ELoc = Tok.getLocation();4171    ExprResult LHS(4172        ParseCastExpression(CastParseKind::AnyCastExpr, false,4173                            TypoCorrectionTypeBehavior::AllowNonTypes));4174    Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);4175    Val =4176        Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);4177  }4178 4179  // Parse ')'.4180  SourceLocation RLoc = Tok.getLocation();4181  if (!T.consumeClose())4182    RLoc = T.getCloseLocation();4183 4184  if (NeedAnExpression && Val.isInvalid())4185    return nullptr;4186 4187  if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&4188      (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||4189       static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {4190    Diag(KLoc[0], diag::err_omp_invalid_dsa)4191        << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==4192                                       OMP_DEFAULT_private4193                                   ? OMPC_private4194                                   : OMPC_firstprivate)4195        << getOpenMPClauseName(OMPC_default) << "5.1";4196    return nullptr;4197  }4198 4199  if (ParseOnly)4200    return nullptr;4201  return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(4202      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);4203}4204 4205static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,4206                             UnqualifiedId &ReductionId) {4207  if (ReductionIdScopeSpec.isEmpty()) {4208    auto OOK = OO_None;4209    switch (P.getCurToken().getKind()) {4210    case tok::plus:4211      OOK = OO_Plus;4212      break;4213    case tok::minus:4214      OOK = OO_Minus;4215      break;4216    case tok::star:4217      OOK = OO_Star;4218      break;4219    case tok::amp:4220      OOK = OO_Amp;4221      break;4222    case tok::pipe:4223      OOK = OO_Pipe;4224      break;4225    case tok::caret:4226      OOK = OO_Caret;4227      break;4228    case tok::ampamp:4229      OOK = OO_AmpAmp;4230      break;4231    case tok::pipepipe:4232      OOK = OO_PipePipe;4233      break;4234    default:4235      break;4236    }4237    if (OOK != OO_None) {4238      SourceLocation OpLoc = P.ConsumeToken();4239      SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};4240      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);4241      return false;4242    }4243  }4244  return P.ParseUnqualifiedId(4245      ReductionIdScopeSpec, /*ObjectType=*/nullptr,4246      /*ObjectHadErrors=*/false, /*EnteringContext*/ false,4247      /*AllowDestructorName*/ false,4248      /*AllowConstructorName*/ false,4249      /*AllowDeductionGuide*/ false, nullptr, ReductionId);4250}4251 4252/// Checks if the token is a valid map-type-modifier.4253/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.4254static OpenMPMapModifierKind isMapModifier(Parser &P) {4255  Token Tok = P.getCurToken();4256  if (!Tok.is(tok::identifier))4257    return OMPC_MAP_MODIFIER_unknown;4258 4259  Preprocessor &PP = P.getPreprocessor();4260  OpenMPMapModifierKind TypeModifier =4261      static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(4262          OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));4263  return TypeModifier;4264}4265 4266bool Parser::parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data) {4267  // Parse '('.4268  BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);4269  if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {4270    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,4271              StopBeforeMatch);4272    return true;4273  }4274  // Parse mapper-identifier4275  if (getLangOpts().CPlusPlus)4276    ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,4277                                   /*ObjectType=*/nullptr,4278                                   /*ObjectHasErrors=*/false,4279                                   /*EnteringContext=*/false);4280  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {4281    Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);4282    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,4283              StopBeforeMatch);4284    return true;4285  }4286  auto &DeclNames = Actions.getASTContext().DeclarationNames;4287  Data.ReductionOrMapperId = DeclarationNameInfo(4288      DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());4289  ConsumeToken();4290  // Parse ')'.4291  return T.consumeClose();4292}4293 4294static OpenMPMapClauseKind isMapType(Parser &P);4295 4296bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) {4297  bool HasMapType = false;4298  SourceLocation PreMapLoc = Tok.getLocation();4299  StringRef PreMapName = "";4300  while (getCurToken().isNot(tok::colon)) {4301    OpenMPMapModifierKind TypeModifier = isMapModifier(*this);4302    OpenMPMapClauseKind MapKind = isMapType(*this);4303    if (TypeModifier == OMPC_MAP_MODIFIER_always ||4304        TypeModifier == OMPC_MAP_MODIFIER_close ||4305        TypeModifier == OMPC_MAP_MODIFIER_present ||4306        TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {4307      Data.MapTypeModifiers.push_back(TypeModifier);4308      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());4309      if (PP.LookAhead(0).isNot(tok::comma) &&4310          PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)4311        Diag(Tok.getLocation(), diag::err_omp_missing_comma)4312            << "map type modifier";4313      ConsumeToken();4314    } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {4315      Data.MapTypeModifiers.push_back(TypeModifier);4316      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());4317      ConsumeToken();4318      if (parseMapperModifier(Data))4319        return true;4320      if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&4321          getLangOpts().OpenMP >= 52)4322        Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)4323            << "map type modifier";4324 4325    } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {4326      if (!HasMapType) {4327        HasMapType = true;4328        Data.ExtraModifier = MapKind;4329        MapKind = OMPC_MAP_unknown;4330        PreMapLoc = Tok.getLocation();4331        PreMapName = Tok.getIdentifierInfo()->getName();4332      } else {4333        Diag(Tok, diag::err_omp_more_one_map_type);4334        Diag(PreMapLoc, diag::note_previous_map_type_specified_here)4335            << PreMapName;4336      }4337      ConsumeToken();4338    } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {4339      Data.MapTypeModifiers.push_back(TypeModifier);4340      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());4341      if (PP.LookAhead(0).isNot(tok::comma) &&4342          PP.LookAhead(0).isNot(tok::colon))4343        Diag(Tok.getLocation(), diag::err_omp_missing_comma)4344            << "map type modifier";4345      if (getLangOpts().OpenMP < 60)4346        Diag(Tok, diag::err_omp_unknown_map_type_modifier)4347            << (getLangOpts().OpenMP >= 514348                    ? (getLangOpts().OpenMP >= 52 ? 2 : 1)4349                    : 0)4350            << getLangOpts().OpenMPExtensions << 0;4351      ConsumeToken();4352    } else {4353      // For the case of unknown map-type-modifier or a map-type.4354      // Map-type is followed by a colon; the function returns when it4355      // encounters a token followed by a colon.4356      if (Tok.is(tok::comma)) {4357        Diag(Tok, diag::err_omp_map_type_modifier_missing);4358        ConsumeToken();4359        continue;4360      }4361      // Potential map-type token as it is followed by a colon.4362      if (PP.LookAhead(0).is(tok::colon)) {4363        if (getLangOpts().OpenMP >= 60) {4364          break;4365        } else {4366          return false;4367        }4368      }4369 4370      Diag(Tok, diag::err_omp_unknown_map_type_modifier)4371          << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)4372                                         : 0)4373          << getLangOpts().OpenMPExtensions4374          << (getLangOpts().OpenMP >= 60 ? 1 : 0);4375      ConsumeToken();4376    }4377    if (getCurToken().is(tok::comma))4378      ConsumeToken();4379  }4380  if (getLangOpts().OpenMP >= 60 && !HasMapType) {4381    if (!Tok.is(tok::colon)) {4382      Diag(Tok, diag::err_omp_unknown_map_type);4383      ConsumeToken();4384    } else {4385      Data.ExtraModifier = OMPC_MAP_unknown;4386    }4387  }4388  return false;4389}4390 4391/// Checks if the token is a valid map-type.4392/// If it is not MapType kind, OMPC_MAP_unknown is returned.4393static OpenMPMapClauseKind isMapType(Parser &P) {4394  Token Tok = P.getCurToken();4395  // The map-type token can be either an identifier or the C++ delete keyword.4396  if (!Tok.isOneOf(tok::identifier, tok::kw_delete))4397    return OMPC_MAP_unknown;4398  Preprocessor &PP = P.getPreprocessor();4399  unsigned MapType =4400      getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts());4401  if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||4402      MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||4403      MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)4404    return static_cast<OpenMPMapClauseKind>(MapType);4405  return OMPC_MAP_unknown;4406}4407 4408/// Parse map-type in map clause.4409/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)4410/// where, map-type ::= to | from | tofrom | alloc | release | delete4411static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data) {4412  Token Tok = P.getCurToken();4413  if (Tok.is(tok::colon)) {4414    P.Diag(Tok, diag::err_omp_map_type_missing);4415    return;4416  }4417  Data.ExtraModifier = isMapType(P);4418  if (Data.ExtraModifier == OMPC_MAP_unknown)4419    P.Diag(Tok, diag::err_omp_unknown_map_type);4420  P.ConsumeToken();4421}4422 4423ExprResult Parser::ParseOpenMPIteratorsExpr() {4424  assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&4425         "Expected 'iterator' token.");4426  SourceLocation IteratorKwLoc = ConsumeToken();4427 4428  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);4429  if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))4430    return ExprError();4431 4432  SourceLocation LLoc = T.getOpenLocation();4433  SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;4434  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {4435    // Check if the type parsing is required.4436    ParsedType IteratorType;4437    if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {4438      // identifier '=' is not found - parse type.4439      TypeResult TR = ParseTypeName();4440      if (TR.isInvalid()) {4441        T.skipToEnd();4442        return ExprError();4443      }4444      IteratorType = TR.get();4445    }4446 4447    // Parse identifier.4448    IdentifierInfo *II = nullptr;4449    SourceLocation IdLoc;4450    if (Tok.is(tok::identifier)) {4451      II = Tok.getIdentifierInfo();4452      IdLoc = ConsumeToken();4453    } else {4454      Diag(Tok, diag::err_expected_unqualified_id) << 0;4455    }4456 4457    // Parse '='.4458    SourceLocation AssignLoc;4459    if (Tok.is(tok::equal))4460      AssignLoc = ConsumeToken();4461    else4462      Diag(Tok, diag::err_omp_expected_equal_in_iterator);4463 4464    // Parse range-specification - <begin> ':' <end> [ ':' <step> ]4465    ColonProtectionRAIIObject ColonRAII(*this);4466    // Parse <begin>4467    SourceLocation Loc = Tok.getLocation();4468    ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);4469    ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);4470    Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,4471                                        /*DiscardedValue=*/false);4472    // Parse ':'.4473    SourceLocation ColonLoc;4474    if (Tok.is(tok::colon))4475      ColonLoc = ConsumeToken();4476 4477    // Parse <end>4478    Loc = Tok.getLocation();4479    LHS = ParseCastExpression(CastParseKind::AnyCastExpr);4480    ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);4481    End = Actions.ActOnFinishFullExpr(End.get(), Loc,4482                                      /*DiscardedValue=*/false);4483 4484    SourceLocation SecColonLoc;4485    ExprResult Step;4486    // Parse optional step.4487    if (Tok.is(tok::colon)) {4488      // Parse ':'4489      SecColonLoc = ConsumeToken();4490      // Parse <step>4491      Loc = Tok.getLocation();4492      LHS = ParseCastExpression(CastParseKind::AnyCastExpr);4493      Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);4494      Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,4495                                         /*DiscardedValue=*/false);4496    }4497 4498    // Parse ',' or ')'4499    if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))4500      Diag(Tok, diag::err_omp_expected_punc_after_iterator);4501    if (Tok.is(tok::comma))4502      ConsumeToken();4503 4504    SemaOpenMP::OMPIteratorData &D = Data.emplace_back();4505    D.DeclIdent = II;4506    D.DeclIdentLoc = IdLoc;4507    D.Type = IteratorType;4508    D.AssignLoc = AssignLoc;4509    D.ColonLoc = ColonLoc;4510    D.SecColonLoc = SecColonLoc;4511    D.Range.Begin = Begin.get();4512    D.Range.End = End.get();4513    D.Range.Step = Step.get();4514  }4515 4516  // Parse ')'.4517  SourceLocation RLoc = Tok.getLocation();4518  if (!T.consumeClose())4519    RLoc = T.getCloseLocation();4520 4521  return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,4522                                               LLoc, RLoc, Data);4523}4524 4525bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,4526                                        SemaOpenMP::OpenMPVarListDataTy &Data,4527                                        const LangOptions &LangOpts) {4528  // Currently the only reserved locator is 'omp_all_memory' which is only4529  // allowed on a depend clause.4530  if (Kind != OMPC_depend || LangOpts.OpenMP < 51)4531    return false;4532 4533  if (Tok.is(tok::identifier) &&4534      Tok.getIdentifierInfo()->isStr("omp_all_memory")) {4535 4536    if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||4537        Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)4538      Diag(Tok, diag::warn_omp_more_one_omp_all_memory);4539    else if (Data.ExtraModifier != OMPC_DEPEND_out &&4540             Data.ExtraModifier != OMPC_DEPEND_inout)4541      Diag(Tok, diag::err_omp_requires_out_inout_depend_type);4542    else4543      Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out4544                               ? OMPC_DEPEND_outallmemory4545                               : OMPC_DEPEND_inoutallmemory;4546    ConsumeToken();4547    return true;4548  }4549  return false;4550}4551 4552/// Parse step size expression. Returns true if parsing is successfull,4553/// otherwise returns false.4554static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data,4555                          OpenMPClauseKind CKind, SourceLocation ELoc) {4556  ExprResult Tail = P.ParseAssignmentExpression();4557  Sema &Actions = P.getActions();4558  Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,4559                                     /*DiscardedValue*/ false);4560  if (Tail.isUsable()) {4561    Data.DepModOrTailExpr = Tail.get();4562    Token CurTok = P.getCurToken();4563    if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {4564      P.Diag(CurTok, diag::err_expected_punc) << "step expression";4565    }4566    return true;4567  }4568  return false;4569}4570 4571/// Parse 'allocate' clause modifiers.4572///   If allocator-modifier exists, return an expression for it. For both4573///   allocator and align modifiers, set Data fields as appropriate.4574static ExprResult4575parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind,4576                                   SemaOpenMP::OpenMPVarListDataTy &Data) {4577  const Token &Tok = P.getCurToken();4578  Preprocessor &PP = P.getPreprocessor();4579  ExprResult Tail;4580  ExprResult Val;4581  SourceLocation RLoc;4582  bool AllocatorSeen = false;4583  bool AlignSeen = false;4584  SourceLocation CurrentModifierLoc = Tok.getLocation();4585  auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(4586      getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));4587 4588  // Modifiers did not exist before 5.14589  if (P.getLangOpts().OpenMP < 51)4590    return P.ParseAssignmentExpression();4591 4592  // An allocator-simple-modifier is exclusive and must appear alone. See4593  // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,4594  // description of "exclusive" property. If we don't recognized an explicit4595  // simple-/complex- modifier, assume we're looking at expression4596  // representing allocator and consider ourselves done.4597  if (CurrentModifier == OMPC_ALLOCATE_unknown)4598    return P.ParseAssignmentExpression();4599 4600  do {4601    P.ConsumeToken();4602    if (Tok.is(tok::l_paren)) {4603      switch (CurrentModifier) {4604      case OMPC_ALLOCATE_allocator: {4605        if (AllocatorSeen) {4606          P.Diag(Tok, diag::err_omp_duplicate_modifier)4607              << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)4608              << getOpenMPClauseName(Kind);4609        } else {4610          Data.AllocClauseModifiers.push_back(CurrentModifier);4611          Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);4612        }4613        BalancedDelimiterTracker AllocateT(P, tok::l_paren,4614                                           tok::annot_pragma_openmp_end);4615        AllocateT.consumeOpen();4616        Tail = P.ParseAssignmentExpression();4617        AllocateT.consumeClose();4618        AllocatorSeen = true;4619        break;4620      }4621      case OMPC_ALLOCATE_align: {4622        if (AlignSeen) {4623          P.Diag(Tok, diag::err_omp_duplicate_modifier)4624              << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)4625              << getOpenMPClauseName(Kind);4626        } else {4627          Data.AllocClauseModifiers.push_back(CurrentModifier);4628          Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);4629        }4630        Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);4631        if (Val.isUsable())4632          Data.AllocateAlignment = Val.get();4633        AlignSeen = true;4634        break;4635      }4636      default:4637        llvm_unreachable("Unexpected allocate modifier");4638      }4639    } else {4640      P.Diag(Tok, diag::err_expected) << tok::l_paren;4641    }4642    if (Tok.isNot(tok::comma))4643      break;4644    P.ConsumeToken();4645    CurrentModifierLoc = Tok.getLocation();4646    CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(4647        getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));4648    // A modifier followed by a comma implies another modifier.4649    if (CurrentModifier == OMPC_ALLOCATE_unknown) {4650      P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);4651      break;4652    }4653  } while (!AllocatorSeen || !AlignSeen);4654  return Tail;4655}4656 4657bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,4658                                OpenMPClauseKind Kind,4659                                SmallVectorImpl<Expr *> &Vars,4660                                SemaOpenMP::OpenMPVarListDataTy &Data) {4661  UnqualifiedId UnqualifiedReductionId;4662  bool InvalidReductionId = false;4663  bool IsInvalidMapperModifier = false;4664 4665  // Parse '('.4666  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);4667  if (T.expectAndConsume(diag::err_expected_lparen_after,4668                         getOpenMPClauseName(Kind).data()))4669    return true;4670 4671  bool HasIterator = false;4672  bool InvalidIterator = false;4673  bool NeedRParenForLinear = false;4674  BalancedDelimiterTracker LinearT(*this, tok::l_paren,4675                                   tok::annot_pragma_openmp_end);4676  // Handle reduction-identifier for reduction clause.4677  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||4678      Kind == OMPC_in_reduction) {4679    Data.ExtraModifier = OMPC_REDUCTION_unknown;4680    if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&4681        (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&4682        NextToken().is(tok::comma)) {4683      // Parse optional reduction modifier.4684      Data.ExtraModifier =4685          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());4686      Data.ExtraModifierLoc = Tok.getLocation();4687      ConsumeToken();4688      assert(Tok.is(tok::comma) && "Expected comma.");4689      (void)ConsumeToken();4690    }4691    // Handle original(private / shared) Modifier4692    if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&4693        Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&4694        NextToken().is(tok::l_paren)) {4695      // Parse original(private) modifier.4696      ConsumeToken();4697      BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);4698      ParenT.consumeOpen();4699      if (Tok.is(tok::kw_private)) {4700        Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;4701        Data.OriginalSharingModifierLoc = Tok.getLocation();4702        ConsumeToken();4703      } else if (Tok.is(tok::identifier) &&4704                 (PP.getSpelling(Tok) == "shared" ||4705                  PP.getSpelling(Tok) == "default")) {4706        Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;4707        Data.OriginalSharingModifierLoc = Tok.getLocation();4708        ConsumeToken();4709      } else {4710        Diag(Tok.getLocation(), diag::err_expected)4711            << "'private or shared or default'";4712        SkipUntil(tok::r_paren);4713        return false;4714      }4715      ParenT.consumeClose();4716      if (!Tok.is(tok::comma)) {4717        Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";4718        return false;4719      }4720      (void)ConsumeToken();4721    }4722    ColonProtectionRAIIObject ColonRAII(*this);4723    if (getLangOpts().CPlusPlus)4724      ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,4725                                     /*ObjectType=*/nullptr,4726                                     /*ObjectHasErrors=*/false,4727                                     /*EnteringContext=*/false);4728    InvalidReductionId = ParseReductionId(4729        *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);4730    if (InvalidReductionId) {4731      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,4732                StopBeforeMatch);4733    }4734    if (Tok.is(tok::colon))4735      Data.ColonLoc = ConsumeToken();4736    else4737      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";4738    if (!InvalidReductionId)4739      Data.ReductionOrMapperId =4740          Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);4741  } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {4742    if (getLangOpts().OpenMP >= 50) {4743      if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {4744        // Handle optional dependence modifier.4745        // iterator(iterators-definition)4746        // where iterators-definition is iterator-specifier [,4747        // iterators-definition ]4748        // where iterator-specifier is [ iterator-type ] identifier =4749        // range-specification4750        HasIterator = true;4751        EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);4752        ExprResult IteratorRes = ParseOpenMPIteratorsExpr();4753        Data.DepModOrTailExpr = IteratorRes.get();4754        // Parse ','4755        ExpectAndConsume(tok::comma);4756      }4757    }4758    // Handle dependency type for depend clause.4759    ColonProtectionRAIIObject ColonRAII(*this);4760    Data.ExtraModifier = getOpenMPSimpleClauseType(4761        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",4762        getLangOpts());4763    Data.ExtraModifierLoc = Tok.getLocation();4764    if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||4765        (Kind == OMPC_doacross &&4766         Data.ExtraModifier == OMPC_DOACROSS_unknown)) {4767      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,4768                StopBeforeMatch);4769    } else {4770      ConsumeToken();4771      // Special processing for depend(source) clause.4772      if (DKind == OMPD_ordered && Kind == OMPC_depend &&4773          Data.ExtraModifier == OMPC_DEPEND_source) {4774        // Parse ')'.4775        T.consumeClose();4776        return false;4777      }4778    }4779    if (Tok.is(tok::colon)) {4780      Data.ColonLoc = ConsumeToken();4781    } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {4782      Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren4783                                      : diag::warn_pragma_expected_colon)4784          << (Kind == OMPC_depend ? "dependency type" : "dependence-type");4785    }4786    if (Kind == OMPC_doacross) {4787      if (Tok.is(tok::identifier) &&4788          Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {4789        Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source4790                                 ? OMPC_DOACROSS_source_omp_cur_iteration4791                                 : OMPC_DOACROSS_sink_omp_cur_iteration;4792        ConsumeToken();4793      }4794      if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {4795        if (Tok.isNot(tok::minus)) {4796          Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)4797              << getOpenMPClauseName(Kind) << 0 << 0;4798          SkipUntil(tok::r_paren);4799          return false;4800        } else {4801          ConsumeToken();4802          SourceLocation Loc = Tok.getLocation();4803          uint64_t Value = 0;4804          if (Tok.isNot(tok::numeric_constant) ||4805              (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {4806            Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)4807                << getOpenMPClauseName(Kind) << 0 << 0;4808            SkipUntil(tok::r_paren);4809            return false;4810          }4811        }4812      }4813      if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {4814        if (Tok.isNot(tok::r_paren)) {4815          Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)4816              << getOpenMPClauseName(Kind) << 1 << 1;4817          SkipUntil(tok::r_paren);4818          return false;4819        }4820      }4821      // Only the 'sink' case has the expression list.4822      if (Kind == OMPC_doacross &&4823          (Data.ExtraModifier == OMPC_DOACROSS_source ||4824           Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||4825           Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {4826        // Parse ')'.4827        T.consumeClose();4828        return false;4829      }4830    }4831  } else if (Kind == OMPC_linear) {4832    // Try to parse modifier if any.4833    Data.ExtraModifier = OMPC_LINEAR_val;4834    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {4835      Data.ExtraModifier =4836          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());4837      Data.ExtraModifierLoc = ConsumeToken();4838      LinearT.consumeOpen();4839      NeedRParenForLinear = true;4840      if (getLangOpts().OpenMP >= 52)4841        Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)4842            << "linear-modifier(list)" << getOpenMPClauseName(Kind)4843            << "linear(list: [linear-modifier,] step(step-size))";4844    }4845  } else if (Kind == OMPC_lastprivate) {4846    // Try to parse modifier if any.4847    Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;4848    // Conditional modifier allowed only in OpenMP 5.0 and not supported in4849    // distribute and taskloop based directives.4850    if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&4851         !isOpenMPTaskLoopDirective(DKind)) &&4852        Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {4853      Data.ExtraModifier =4854          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());4855      Data.ExtraModifierLoc = Tok.getLocation();4856      ConsumeToken();4857      assert(Tok.is(tok::colon) && "Expected colon.");4858      Data.ColonLoc = ConsumeToken();4859    }4860  } else if (Kind == OMPC_map) {4861    // Handle optional iterator map modifier.4862    if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {4863      HasIterator = true;4864      EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);4865      Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);4866      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());4867      ExprResult IteratorRes = ParseOpenMPIteratorsExpr();4868      Data.IteratorExpr = IteratorRes.get();4869      // Parse ','4870      ExpectAndConsume(tok::comma);4871      if (getLangOpts().OpenMP < 52) {4872        Diag(Tok, diag::err_omp_unknown_map_type_modifier)4873            << (getLangOpts().OpenMP >= 51 ? 1 : 0)4874            << getLangOpts().OpenMPExtensions << 0;4875        InvalidIterator = true;4876      }4877    }4878    // Handle map type for map clause.4879    ColonProtectionRAIIObject ColonRAII(*this);4880 4881    // The first identifier may be a list item, a map-type or a4882    // map-type-modifier. The map-type can also be delete which has the same4883    // spelling of the C++ delete keyword.4884    Data.ExtraModifier = OMPC_MAP_unknown;4885    Data.ExtraModifierLoc = Tok.getLocation();4886 4887    // Check for presence of a colon in the map clause.4888    TentativeParsingAction TPA(*this);4889    bool ColonPresent = false;4890    if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,4891                  StopBeforeMatch)) {4892      if (Tok.is(tok::colon))4893        ColonPresent = true;4894    }4895    TPA.Revert();4896    // Only parse map-type-modifier[s] and map-type if a colon is present in4897    // the map clause.4898    if (ColonPresent) {4899      if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))4900        Diag(Tok, diag::err_omp_map_modifier_specification_list);4901      IsInvalidMapperModifier = parseMapTypeModifiers(Data);4902      if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)4903        parseMapType(*this, Data);4904      else4905        SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);4906    }4907    if (Data.ExtraModifier == OMPC_MAP_unknown) {4908      Data.ExtraModifier = OMPC_MAP_tofrom;4909      if (getLangOpts().OpenMP >= 52) {4910        if (DKind == OMPD_target_enter_data)4911          Data.ExtraModifier = OMPC_MAP_to;4912        else if (DKind == OMPD_target_exit_data)4913          Data.ExtraModifier = OMPC_MAP_from;4914      }4915      Data.IsMapTypeImplicit = true;4916    }4917 4918    if (Tok.is(tok::colon))4919      Data.ColonLoc = ConsumeToken();4920  } else if (Kind == OMPC_to || Kind == OMPC_from) {4921    while (Tok.is(tok::identifier)) {4922      auto Modifier = static_cast<OpenMPMotionModifierKind>(4923          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));4924      if (Modifier == OMPC_MOTION_MODIFIER_unknown)4925        break;4926      Data.MotionModifiers.push_back(Modifier);4927      Data.MotionModifiersLoc.push_back(Tok.getLocation());4928      if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {4929        ExprResult Tail;4930        Tail = ParseOpenMPIteratorsExpr();4931        Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),4932                                           /*DiscardedValue=*/false);4933        if (Tail.isUsable())4934          Data.IteratorExpr = Tail.get();4935      } else {4936        ConsumeToken();4937        if (Modifier == OMPC_MOTION_MODIFIER_mapper) {4938          IsInvalidMapperModifier = parseMapperModifier(Data);4939          if (IsInvalidMapperModifier)4940            break;4941        }4942        // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.4943        if (getLangOpts().OpenMP < 51)4944          break;4945        // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.4946        // TODO: Is that intentional?4947        if (Tok.is(tok::comma))4948          ConsumeToken();4949      }4950    }4951    if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {4952      if (!IsInvalidMapperModifier) {4953        if (getLangOpts().OpenMP < 51)4954          Diag(Tok, diag::warn_pragma_expected_colon) << ")";4955        else4956          Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";4957      }4958      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,4959                StopBeforeMatch);4960    }4961    // OpenMP 5.1 permits a ':' even without a preceding modifier.  TODO: Is4962    // that intentional?4963    if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&4964        Tok.is(tok::colon))4965      Data.ColonLoc = ConsumeToken();4966  } else if (Kind == OMPC_allocate ||4967             (Kind == OMPC_affinity && Tok.is(tok::identifier) &&4968              PP.getSpelling(Tok) == "iterator")) {4969    // Handle optional allocator and align modifiers followed by colon4970    // delimiter.4971    ColonProtectionRAIIObject ColonRAII(*this);4972    TentativeParsingAction TPA(*this);4973    // OpenMP 5.0, 2.10.1, task Construct.4974    // where aff-modifier is one of the following:4975    // iterator(iterators-definition)4976    ExprResult Tail;4977    if (Kind == OMPC_allocate) {4978      Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);4979    } else {4980      HasIterator = true;4981      EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);4982      Tail = ParseOpenMPIteratorsExpr();4983    }4984    Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),4985                                       /*DiscardedValue=*/false);4986    if (Tail.isUsable() || Data.AllocateAlignment) {4987      if (Tok.is(tok::colon)) {4988        Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;4989        Data.ColonLoc = ConsumeToken();4990        TPA.Commit();4991      } else {4992        // Colon not found, parse only list of variables.4993        TPA.Revert();4994        if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {4995          SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,4996                    StopBeforeMatch);4997          Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";4998        }4999      }5000    } else {5001      // Parsing was unsuccessfull, revert and skip to the end of clause or5002      // directive.5003      TPA.Revert();5004      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,5005                StopBeforeMatch);5006    }5007  } else if (Kind == OMPC_adjust_args) {5008    // Handle adjust-op for adjust_args clause.5009    ColonProtectionRAIIObject ColonRAII(*this);5010    Data.ExtraModifier = getOpenMPSimpleClauseType(5011        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",5012        getLangOpts());5013    Data.ExtraModifierLoc = Tok.getLocation();5014    if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {5015      Diag(Tok, diag::err_omp_unknown_adjust_args_op)5016          << (getLangOpts().OpenMP >= 60 ? 1 : 0);5017      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);5018    } else {5019      ConsumeToken();5020      if (Tok.is(tok::colon))5021        Data.ColonLoc = Tok.getLocation();5022      if (getLangOpts().OpenMP >= 61) {5023        // Handle the optional fallback argument for the need_device_ptr5024        // modifier.5025        if (Tok.is(tok::l_paren)) {5026          BalancedDelimiterTracker T(*this, tok::l_paren);5027          T.consumeOpen();5028          if (Tok.is(tok::identifier)) {5029            std::string Modifier = PP.getSpelling(Tok);5030            if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {5031              Data.NeedDevicePtrModifier =5032                  Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify5033                                           : OMPC_NEED_DEVICE_PTR_fb_preserve;5034            } else {5035              Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);5036              SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,5037                        StopBeforeMatch);5038              return false;5039            }5040            ConsumeToken();5041            if (Tok.is(tok::r_paren)) {5042              Data.NeedDevicePtrModifierLoc = Tok.getLocation();5043              ConsumeAnyToken();5044            } else {5045              Diag(Tok, diag::err_expected) << tok::r_paren;5046              SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,5047                        StopBeforeMatch);5048              return false;5049            }5050          }5051        }5052      }5053      ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,5054                       "adjust-op");5055    }5056  }5057 5058  bool IsComma =5059      (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&5060       Kind != OMPC_in_reduction && Kind != OMPC_depend &&5061       Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||5062      (Kind == OMPC_reduction && !InvalidReductionId) ||5063      (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||5064      (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||5065      (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||5066      (Kind == OMPC_adjust_args &&5067       Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);5068  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);5069  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&5070                     Tok.isNot(tok::annot_pragma_openmp_end))) {5071    ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);5072    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);5073    if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {5074      // Parse variable5075      ExprResult VarExpr = ParseAssignmentExpression();5076      if (VarExpr.isUsable()) {5077        Vars.push_back(VarExpr.get());5078      } else {5079        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,5080                  StopBeforeMatch);5081      }5082    }5083    // Skip ',' if any5084    IsComma = Tok.is(tok::comma);5085    if (IsComma)5086      ConsumeToken();5087    else if (Tok.isNot(tok::r_paren) &&5088             Tok.isNot(tok::annot_pragma_openmp_end) &&5089             (!MayHaveTail || Tok.isNot(tok::colon))) {5090      unsigned OMPVersion = Actions.getLangOpts().OpenMP;5091      Diag(Tok, diag::err_omp_expected_punc)5092          << ((Kind == OMPC_flush)5093                  ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)5094                  : getOpenMPClauseName(Kind))5095          << (Kind == OMPC_flush);5096    }5097  }5098 5099  // Parse ')' for linear clause with modifier.5100  if (NeedRParenForLinear)5101    LinearT.consumeClose();5102  // Parse ':' linear modifiers (val, uval, ref or step(step-size))5103  // or parse ':' alignment.5104  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);5105  bool StepFound = false;5106  bool ModifierFound = false;5107  if (MustHaveTail) {5108    Data.ColonLoc = Tok.getLocation();5109    SourceLocation ELoc = ConsumeToken();5110 5111    if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {5112      bool Malformed = false;5113      while (Tok.isNot(tok::r_paren)) {5114        if (Tok.is(tok::identifier)) {5115          // identifier could be a linear kind (val, uval, ref) or step5116          // modifier or step size5117          OpenMPLinearClauseKind LinKind =5118              static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType(5119                  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),5120                  getLangOpts()));5121 5122          if (LinKind == OMPC_LINEAR_step) {5123            if (StepFound)5124              Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;5125 5126            BalancedDelimiterTracker StepT(*this, tok::l_paren,5127                                           tok::annot_pragma_openmp_end);5128            SourceLocation StepModifierLoc = ConsumeToken();5129            // parse '('5130            if (StepT.consumeOpen())5131              Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";5132 5133            // parse step size expression5134            StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());5135            if (StepFound)5136              Data.StepModifierLoc = StepModifierLoc;5137 5138            // parse ')'5139            StepT.consumeClose();5140          } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {5141            if (ModifierFound)5142              Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;5143 5144            Data.ExtraModifier = LinKind;5145            Data.ExtraModifierLoc = ConsumeToken();5146            ModifierFound = true;5147          } else {5148            StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());5149            if (!StepFound) {5150              Malformed = true;5151              SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,5152                        StopBeforeMatch);5153            }5154          }5155        } else {5156          // parse an integer expression as step size5157          StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());5158        }5159 5160        if (Tok.is(tok::comma))5161          ConsumeToken();5162        if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))5163          break;5164      }5165      if (!Malformed && !StepFound && !ModifierFound)5166        Diag(ELoc, diag::err_expected_expression);5167    } else {5168      // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)5169      ExprResult Tail = ParseAssignmentExpression();5170      Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,5171                                         /*DiscardedValue*/ false);5172      if (Tail.isUsable())5173        Data.DepModOrTailExpr = Tail.get();5174      else5175        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,5176                  StopBeforeMatch);5177    }5178  }5179 5180  // Parse ')'.5181  Data.RLoc = Tok.getLocation();5182  if (!T.consumeClose())5183    Data.RLoc = T.getCloseLocation();5184  // Exit from scope when the iterator is used in depend clause.5185  if (HasIterator)5186    ExitScope();5187  return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&5188          Vars.empty()) ||5189         (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||5190         InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;5191}5192 5193OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,5194                                            OpenMPClauseKind Kind,5195                                            bool ParseOnly) {5196  SourceLocation Loc = Tok.getLocation();5197  SourceLocation LOpen = ConsumeToken();5198  SmallVector<Expr *, 4> Vars;5199  SemaOpenMP::OpenMPVarListDataTy Data;5200 5201  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))5202    return nullptr;5203 5204  if (ParseOnly)5205    return nullptr;5206  OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);5207  return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);5208}5209 5210bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,5211                                       SourceLocation &ClauseNameLoc,5212                                       SourceLocation &OpenLoc,5213                                       SourceLocation &CloseLoc,5214                                       SmallVectorImpl<Expr *> &Exprs,5215                                       bool ReqIntConst) {5216  assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&5217         "Expected parsing to start at clause name");5218  ClauseNameLoc = ConsumeToken();5219 5220  // Parse inside of '(' and ')'.5221  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);5222  if (T.consumeOpen()) {5223    Diag(Tok, diag::err_expected) << tok::l_paren;5224    return true;5225  }5226 5227  // Parse the list with interleaved commas.5228  do {5229    ExprResult Val =5230        ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression();5231    if (!Val.isUsable()) {5232      // Encountered something other than an expression; abort to ')'.5233      T.skipToEnd();5234      return true;5235    }5236    Exprs.push_back(Val.get());5237  } while (TryConsumeToken(tok::comma));5238 5239  bool Result = T.consumeClose();5240  OpenLoc = T.getOpenLocation();5241  CloseLoc = T.getCloseLocation();5242  return Result;5243}5244