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