ParseOpenMP.cpp revision 360784
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/StmtOpenMP.h"
15#include "clang/Basic/OpenMPKinds.h"
16#include "clang/Parse/ParseDiagnostic.h"
17#include "clang/Parse/Parser.h"
18#include "clang/Parse/RAIIObjectsForParser.h"
19#include "clang/Sema/Scope.h"
20#include "llvm/ADT/PointerIntPair.h"
21#include "llvm/ADT/UniqueVector.h"
22
23using namespace clang;
24using namespace llvm::omp;
25
26//===----------------------------------------------------------------------===//
27// OpenMP declarative directives.
28//===----------------------------------------------------------------------===//
29
30namespace {
31enum OpenMPDirectiveKindEx {
32  OMPD_cancellation = unsigned(OMPD_unknown) + 1,
33  OMPD_data,
34  OMPD_declare,
35  OMPD_end,
36  OMPD_end_declare,
37  OMPD_enter,
38  OMPD_exit,
39  OMPD_point,
40  OMPD_reduction,
41  OMPD_target_enter,
42  OMPD_target_exit,
43  OMPD_update,
44  OMPD_distribute_parallel,
45  OMPD_teams_distribute_parallel,
46  OMPD_target_teams_distribute_parallel,
47  OMPD_mapper,
48  OMPD_variant,
49};
50
51// Helper to unify the enum class OpenMPDirectiveKind with its extension
52// the OpenMPDirectiveKindEx enum which allows to use them together as if they
53// are unsigned values.
54struct OpenMPDirectiveKindExWrapper {
55  OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
56  OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
57  bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
58  bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
59  bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
60  operator unsigned() const { return Value; }
61  operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
62  unsigned Value;
63};
64
65class DeclDirectiveListParserHelper final {
66  SmallVector<Expr *, 4> Identifiers;
67  Parser *P;
68  OpenMPDirectiveKind Kind;
69
70public:
71  DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
72      : P(P), Kind(Kind) {}
73  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
74    ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
75        P->getCurScope(), SS, NameInfo, Kind);
76    if (Res.isUsable())
77      Identifiers.push_back(Res.get());
78  }
79  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
80};
81} // namespace
82
83// Map token string to extended OMP token kind that are
84// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
85static unsigned getOpenMPDirectiveKindEx(StringRef S) {
86  OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
87  if (DKind != OMPD_unknown)
88    return DKind;
89
90  return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
91      .Case("cancellation", OMPD_cancellation)
92      .Case("data", OMPD_data)
93      .Case("declare", OMPD_declare)
94      .Case("end", OMPD_end)
95      .Case("enter", OMPD_enter)
96      .Case("exit", OMPD_exit)
97      .Case("point", OMPD_point)
98      .Case("reduction", OMPD_reduction)
99      .Case("update", OMPD_update)
100      .Case("mapper", OMPD_mapper)
101      .Case("variant", OMPD_variant)
102      .Default(OMPD_unknown);
103}
104
105static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
106  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
107  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
108  // TODO: add other combined directives in topological order.
109  static const OpenMPDirectiveKindExWrapper F[][3] = {
110      {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
111      {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
112      {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
113      {OMPD_declare, OMPD_simd, OMPD_declare_simd},
114      {OMPD_declare, OMPD_target, OMPD_declare_target},
115      {OMPD_declare, OMPD_variant, OMPD_declare_variant},
116      {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
117      {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
118      {OMPD_distribute_parallel_for, OMPD_simd,
119       OMPD_distribute_parallel_for_simd},
120      {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
121      {OMPD_end, OMPD_declare, OMPD_end_declare},
122      {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
123      {OMPD_target, OMPD_data, OMPD_target_data},
124      {OMPD_target, OMPD_enter, OMPD_target_enter},
125      {OMPD_target, OMPD_exit, OMPD_target_exit},
126      {OMPD_target, OMPD_update, OMPD_target_update},
127      {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
128      {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
129      {OMPD_for, OMPD_simd, OMPD_for_simd},
130      {OMPD_parallel, OMPD_for, OMPD_parallel_for},
131      {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
132      {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
133      {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
134      {OMPD_target, OMPD_parallel, OMPD_target_parallel},
135      {OMPD_target, OMPD_simd, OMPD_target_simd},
136      {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
137      {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
138      {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
139      {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
140      {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
141      {OMPD_teams_distribute_parallel, OMPD_for,
142       OMPD_teams_distribute_parallel_for},
143      {OMPD_teams_distribute_parallel_for, OMPD_simd,
144       OMPD_teams_distribute_parallel_for_simd},
145      {OMPD_target, OMPD_teams, OMPD_target_teams},
146      {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
147      {OMPD_target_teams_distribute, OMPD_parallel,
148       OMPD_target_teams_distribute_parallel},
149      {OMPD_target_teams_distribute, OMPD_simd,
150       OMPD_target_teams_distribute_simd},
151      {OMPD_target_teams_distribute_parallel, OMPD_for,
152       OMPD_target_teams_distribute_parallel_for},
153      {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
154       OMPD_target_teams_distribute_parallel_for_simd},
155      {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
156      {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
157      {OMPD_parallel, OMPD_master, OMPD_parallel_master},
158      {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
159      {OMPD_parallel_master_taskloop, OMPD_simd,
160       OMPD_parallel_master_taskloop_simd}};
161  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
162  Token Tok = P.getCurToken();
163  OpenMPDirectiveKindExWrapper DKind =
164      Tok.isAnnotation()
165          ? static_cast<unsigned>(OMPD_unknown)
166          : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
167  if (DKind == OMPD_unknown)
168    return OMPD_unknown;
169
170  for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
171    if (DKind != F[I][0])
172      continue;
173
174    Tok = P.getPreprocessor().LookAhead(0);
175    OpenMPDirectiveKindExWrapper SDKind =
176        Tok.isAnnotation()
177            ? static_cast<unsigned>(OMPD_unknown)
178            : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
179    if (SDKind == OMPD_unknown)
180      continue;
181
182    if (SDKind == F[I][1]) {
183      P.ConsumeToken();
184      DKind = F[I][2];
185    }
186  }
187  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
188                              : OMPD_unknown;
189}
190
191static DeclarationName parseOpenMPReductionId(Parser &P) {
192  Token Tok = P.getCurToken();
193  Sema &Actions = P.getActions();
194  OverloadedOperatorKind OOK = OO_None;
195  // Allow to use 'operator' keyword for C++ operators
196  bool WithOperator = false;
197  if (Tok.is(tok::kw_operator)) {
198    P.ConsumeToken();
199    Tok = P.getCurToken();
200    WithOperator = true;
201  }
202  switch (Tok.getKind()) {
203  case tok::plus: // '+'
204    OOK = OO_Plus;
205    break;
206  case tok::minus: // '-'
207    OOK = OO_Minus;
208    break;
209  case tok::star: // '*'
210    OOK = OO_Star;
211    break;
212  case tok::amp: // '&'
213    OOK = OO_Amp;
214    break;
215  case tok::pipe: // '|'
216    OOK = OO_Pipe;
217    break;
218  case tok::caret: // '^'
219    OOK = OO_Caret;
220    break;
221  case tok::ampamp: // '&&'
222    OOK = OO_AmpAmp;
223    break;
224  case tok::pipepipe: // '||'
225    OOK = OO_PipePipe;
226    break;
227  case tok::identifier: // identifier
228    if (!WithOperator)
229      break;
230    LLVM_FALLTHROUGH;
231  default:
232    P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
233    P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
234                Parser::StopBeforeMatch);
235    return DeclarationName();
236  }
237  P.ConsumeToken();
238  auto &DeclNames = Actions.getASTContext().DeclarationNames;
239  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
240                        : DeclNames.getCXXOperatorName(OOK);
241}
242
243/// Parse 'omp declare reduction' construct.
244///
245///       declare-reduction-directive:
246///        annot_pragma_openmp 'declare' 'reduction'
247///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
248///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
249///        annot_pragma_openmp_end
250/// <reduction_id> is either a base language identifier or one of the following
251/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
252///
253Parser::DeclGroupPtrTy
254Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
255  // Parse '('.
256  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
257  if (T.expectAndConsume(
258          diag::err_expected_lparen_after,
259          getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
260    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
261    return DeclGroupPtrTy();
262  }
263
264  DeclarationName Name = parseOpenMPReductionId(*this);
265  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
266    return DeclGroupPtrTy();
267
268  // Consume ':'.
269  bool IsCorrect = !ExpectAndConsume(tok::colon);
270
271  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
272    return DeclGroupPtrTy();
273
274  IsCorrect = IsCorrect && !Name.isEmpty();
275
276  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
277    Diag(Tok.getLocation(), diag::err_expected_type);
278    IsCorrect = false;
279  }
280
281  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
282    return DeclGroupPtrTy();
283
284  SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
285  // Parse list of types until ':' token.
286  do {
287    ColonProtectionRAIIObject ColonRAII(*this);
288    SourceRange Range;
289    TypeResult TR =
290        ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
291    if (TR.isUsable()) {
292      QualType ReductionType =
293          Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
294      if (!ReductionType.isNull()) {
295        ReductionTypes.push_back(
296            std::make_pair(ReductionType, Range.getBegin()));
297      }
298    } else {
299      SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
300                StopBeforeMatch);
301    }
302
303    if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
304      break;
305
306    // Consume ','.
307    if (ExpectAndConsume(tok::comma)) {
308      IsCorrect = false;
309      if (Tok.is(tok::annot_pragma_openmp_end)) {
310        Diag(Tok.getLocation(), diag::err_expected_type);
311        return DeclGroupPtrTy();
312      }
313    }
314  } while (Tok.isNot(tok::annot_pragma_openmp_end));
315
316  if (ReductionTypes.empty()) {
317    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
318    return DeclGroupPtrTy();
319  }
320
321  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
322    return DeclGroupPtrTy();
323
324  // Consume ':'.
325  if (ExpectAndConsume(tok::colon))
326    IsCorrect = false;
327
328  if (Tok.is(tok::annot_pragma_openmp_end)) {
329    Diag(Tok.getLocation(), diag::err_expected_expression);
330    return DeclGroupPtrTy();
331  }
332
333  DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
334      getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
335
336  // Parse <combiner> expression and then parse initializer if any for each
337  // correct type.
338  unsigned I = 0, E = ReductionTypes.size();
339  for (Decl *D : DRD.get()) {
340    TentativeParsingAction TPA(*this);
341    ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
342                                    Scope::CompoundStmtScope |
343                                    Scope::OpenMPDirectiveScope);
344    // Parse <combiner> expression.
345    Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
346    ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
347        ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
348    Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
349
350    if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
351        Tok.isNot(tok::annot_pragma_openmp_end)) {
352      TPA.Commit();
353      IsCorrect = false;
354      break;
355    }
356    IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
357    ExprResult InitializerResult;
358    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
359      // Parse <initializer> expression.
360      if (Tok.is(tok::identifier) &&
361          Tok.getIdentifierInfo()->isStr("initializer")) {
362        ConsumeToken();
363      } else {
364        Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
365        TPA.Commit();
366        IsCorrect = false;
367        break;
368      }
369      // Parse '('.
370      BalancedDelimiterTracker T(*this, tok::l_paren,
371                                 tok::annot_pragma_openmp_end);
372      IsCorrect =
373          !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
374          IsCorrect;
375      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
376        ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
377                                        Scope::CompoundStmtScope |
378                                        Scope::OpenMPDirectiveScope);
379        // Parse expression.
380        VarDecl *OmpPrivParm =
381            Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
382                                                                D);
383        // Check if initializer is omp_priv <init_expr> or something else.
384        if (Tok.is(tok::identifier) &&
385            Tok.getIdentifierInfo()->isStr("omp_priv")) {
386          ConsumeToken();
387          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
388        } else {
389          InitializerResult = Actions.ActOnFinishFullExpr(
390              ParseAssignmentExpression().get(), D->getLocation(),
391              /*DiscardedValue*/ false);
392        }
393        Actions.ActOnOpenMPDeclareReductionInitializerEnd(
394            D, InitializerResult.get(), OmpPrivParm);
395        if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
396            Tok.isNot(tok::annot_pragma_openmp_end)) {
397          TPA.Commit();
398          IsCorrect = false;
399          break;
400        }
401        IsCorrect =
402            !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
403      }
404    }
405
406    ++I;
407    // Revert parsing if not the last type, otherwise accept it, we're done with
408    // parsing.
409    if (I != E)
410      TPA.Revert();
411    else
412      TPA.Commit();
413  }
414  return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
415                                                         IsCorrect);
416}
417
418void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
419  // Parse declarator '=' initializer.
420  // If a '==' or '+=' is found, suggest a fixit to '='.
421  if (isTokenEqualOrEqualTypo()) {
422    ConsumeToken();
423
424    if (Tok.is(tok::code_completion)) {
425      Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
426      Actions.FinalizeDeclaration(OmpPrivParm);
427      cutOffParsing();
428      return;
429    }
430
431    PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
432    ExprResult Init = ParseInitializer();
433
434    if (Init.isInvalid()) {
435      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
436      Actions.ActOnInitializerError(OmpPrivParm);
437    } else {
438      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
439                                   /*DirectInit=*/false);
440    }
441  } else if (Tok.is(tok::l_paren)) {
442    // Parse C++ direct initializer: '(' expression-list ')'
443    BalancedDelimiterTracker T(*this, tok::l_paren);
444    T.consumeOpen();
445
446    ExprVector Exprs;
447    CommaLocsTy CommaLocs;
448
449    SourceLocation LParLoc = T.getOpenLocation();
450    auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
451      QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
452          getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
453          OmpPrivParm->getLocation(), Exprs, LParLoc);
454      CalledSignatureHelp = true;
455      return PreferredType;
456    };
457    if (ParseExpressionList(Exprs, CommaLocs, [&] {
458          PreferredType.enterFunctionArgument(Tok.getLocation(),
459                                              RunSignatureHelp);
460        })) {
461      if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
462        RunSignatureHelp();
463      Actions.ActOnInitializerError(OmpPrivParm);
464      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
465    } else {
466      // Match the ')'.
467      SourceLocation RLoc = Tok.getLocation();
468      if (!T.consumeClose())
469        RLoc = T.getCloseLocation();
470
471      assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
472             "Unexpected number of commas!");
473
474      ExprResult Initializer =
475          Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
476      Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
477                                   /*DirectInit=*/true);
478    }
479  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
480    // Parse C++0x braced-init-list.
481    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
482
483    ExprResult Init(ParseBraceInitializer());
484
485    if (Init.isInvalid()) {
486      Actions.ActOnInitializerError(OmpPrivParm);
487    } else {
488      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
489                                   /*DirectInit=*/true);
490    }
491  } else {
492    Actions.ActOnUninitializedDecl(OmpPrivParm);
493  }
494}
495
496/// Parses 'omp declare mapper' directive.
497///
498///       declare-mapper-directive:
499///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
500///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
501///         annot_pragma_openmp_end
502/// <mapper-identifier> and <var> are base language identifiers.
503///
504Parser::DeclGroupPtrTy
505Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
506  bool IsCorrect = true;
507  // Parse '('
508  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
509  if (T.expectAndConsume(diag::err_expected_lparen_after,
510                         getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
511    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
512    return DeclGroupPtrTy();
513  }
514
515  // Parse <mapper-identifier>
516  auto &DeclNames = Actions.getASTContext().DeclarationNames;
517  DeclarationName MapperId;
518  if (PP.LookAhead(0).is(tok::colon)) {
519    if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
520      Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
521      IsCorrect = false;
522    } else {
523      MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
524    }
525    ConsumeToken();
526    // Consume ':'.
527    ExpectAndConsume(tok::colon);
528  } else {
529    // If no mapper identifier is provided, its name is "default" by default
530    MapperId =
531        DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
532  }
533
534  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
535    return DeclGroupPtrTy();
536
537  // Parse <type> <var>
538  DeclarationName VName;
539  QualType MapperType;
540  SourceRange Range;
541  TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
542  if (ParsedType.isUsable())
543    MapperType =
544        Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
545  if (MapperType.isNull())
546    IsCorrect = false;
547  if (!IsCorrect) {
548    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
549    return DeclGroupPtrTy();
550  }
551
552  // Consume ')'.
553  IsCorrect &= !T.consumeClose();
554  if (!IsCorrect) {
555    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
556    return DeclGroupPtrTy();
557  }
558
559  // Enter scope.
560  OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
561      getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
562      Range.getBegin(), VName, AS);
563  DeclarationNameInfo DirName;
564  SourceLocation Loc = Tok.getLocation();
565  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
566                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
567  ParseScope OMPDirectiveScope(this, ScopeFlags);
568  Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
569
570  // Add the mapper variable declaration.
571  Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
572      DMD, getCurScope(), MapperType, Range.getBegin(), VName);
573
574  // Parse map clauses.
575  SmallVector<OMPClause *, 6> Clauses;
576  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
577    OpenMPClauseKind CKind = Tok.isAnnotation()
578                                 ? OMPC_unknown
579                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
580    Actions.StartOpenMPClause(CKind);
581    OMPClause *Clause =
582        ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
583    if (Clause)
584      Clauses.push_back(Clause);
585    else
586      IsCorrect = false;
587    // Skip ',' if any.
588    if (Tok.is(tok::comma))
589      ConsumeToken();
590    Actions.EndOpenMPClause();
591  }
592  if (Clauses.empty()) {
593    Diag(Tok, diag::err_omp_expected_clause)
594        << getOpenMPDirectiveName(OMPD_declare_mapper);
595    IsCorrect = false;
596  }
597
598  // Exit scope.
599  Actions.EndOpenMPDSABlock(nullptr);
600  OMPDirectiveScope.Exit();
601
602  DeclGroupPtrTy DGP =
603      Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
604  if (!IsCorrect)
605    return DeclGroupPtrTy();
606  return DGP;
607}
608
609TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
610                                                   DeclarationName &Name,
611                                                   AccessSpecifier AS) {
612  // Parse the common declaration-specifiers piece.
613  Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
614  DeclSpec DS(AttrFactory);
615  ParseSpecifierQualifierList(DS, AS, DSC);
616
617  // Parse the declarator.
618  DeclaratorContext Context = DeclaratorContext::PrototypeContext;
619  Declarator DeclaratorInfo(DS, Context);
620  ParseDeclarator(DeclaratorInfo);
621  Range = DeclaratorInfo.getSourceRange();
622  if (DeclaratorInfo.getIdentifier() == nullptr) {
623    Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
624    return true;
625  }
626  Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
627
628  return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
629}
630
631namespace {
632/// RAII that recreates function context for correct parsing of clauses of
633/// 'declare simd' construct.
634/// OpenMP, 2.8.2 declare simd Construct
635/// The expressions appearing in the clauses of this directive are evaluated in
636/// the scope of the arguments of the function declaration or definition.
637class FNContextRAII final {
638  Parser &P;
639  Sema::CXXThisScopeRAII *ThisScope;
640  Parser::ParseScope *TempScope;
641  Parser::ParseScope *FnScope;
642  bool HasTemplateScope = false;
643  bool HasFunScope = false;
644  FNContextRAII() = delete;
645  FNContextRAII(const FNContextRAII &) = delete;
646  FNContextRAII &operator=(const FNContextRAII &) = delete;
647
648public:
649  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
650    Decl *D = *Ptr.get().begin();
651    NamedDecl *ND = dyn_cast<NamedDecl>(D);
652    RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
653    Sema &Actions = P.getActions();
654
655    // Allow 'this' within late-parsed attributes.
656    ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
657                                           ND && ND->isCXXInstanceMember());
658
659    // If the Decl is templatized, add template parameters to scope.
660    HasTemplateScope = D->isTemplateDecl();
661    TempScope =
662        new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
663    if (HasTemplateScope)
664      Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
665
666    // If the Decl is on a function, add function parameters to the scope.
667    HasFunScope = D->isFunctionOrFunctionTemplate();
668    FnScope = new Parser::ParseScope(
669        &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
670        HasFunScope);
671    if (HasFunScope)
672      Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
673  }
674  ~FNContextRAII() {
675    if (HasFunScope) {
676      P.getActions().ActOnExitFunctionContext();
677      FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
678    }
679    if (HasTemplateScope)
680      TempScope->Exit();
681    delete FnScope;
682    delete TempScope;
683    delete ThisScope;
684  }
685};
686} // namespace
687
688/// Parses clauses for 'declare simd' directive.
689///    clause:
690///      'inbranch' | 'notinbranch'
691///      'simdlen' '(' <expr> ')'
692///      { 'uniform' '(' <argument_list> ')' }
693///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
694///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
695static bool parseDeclareSimdClauses(
696    Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
697    SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
698    SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
699    SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
700  SourceRange BSRange;
701  const Token &Tok = P.getCurToken();
702  bool IsError = false;
703  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
704    if (Tok.isNot(tok::identifier))
705      break;
706    OMPDeclareSimdDeclAttr::BranchStateTy Out;
707    IdentifierInfo *II = Tok.getIdentifierInfo();
708    StringRef ClauseName = II->getName();
709    // Parse 'inranch|notinbranch' clauses.
710    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
711      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
712        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
713            << ClauseName
714            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
715        IsError = true;
716      }
717      BS = Out;
718      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
719      P.ConsumeToken();
720    } else if (ClauseName.equals("simdlen")) {
721      if (SimdLen.isUsable()) {
722        P.Diag(Tok, diag::err_omp_more_one_clause)
723            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
724        IsError = true;
725      }
726      P.ConsumeToken();
727      SourceLocation RLoc;
728      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
729      if (SimdLen.isInvalid())
730        IsError = true;
731    } else {
732      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
733      if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
734          CKind == OMPC_linear) {
735        Parser::OpenMPVarListDataTy Data;
736        SmallVectorImpl<Expr *> *Vars = &Uniforms;
737        if (CKind == OMPC_aligned) {
738          Vars = &Aligneds;
739        } else if (CKind == OMPC_linear) {
740          Data.ExtraModifier = OMPC_LINEAR_val;
741          Vars = &Linears;
742        }
743
744        P.ConsumeToken();
745        if (P.ParseOpenMPVarList(OMPD_declare_simd,
746                                 getOpenMPClauseKind(ClauseName), *Vars, Data))
747          IsError = true;
748        if (CKind == OMPC_aligned) {
749          Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
750        } else if (CKind == OMPC_linear) {
751          assert(0 <= Data.ExtraModifier &&
752                 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
753                 "Unexpected linear modifier.");
754          if (P.getActions().CheckOpenMPLinearModifier(
755                  static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
756                  Data.DepLinMapLastLoc))
757            Data.ExtraModifier = OMPC_LINEAR_val;
758          LinModifiers.append(Linears.size() - LinModifiers.size(),
759                              Data.ExtraModifier);
760          Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
761        }
762      } else
763        // TODO: add parsing of other clauses.
764        break;
765    }
766    // Skip ',' if any.
767    if (Tok.is(tok::comma))
768      P.ConsumeToken();
769  }
770  return IsError;
771}
772
773/// Parse clauses for '#pragma omp declare simd'.
774Parser::DeclGroupPtrTy
775Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
776                                   CachedTokens &Toks, SourceLocation Loc) {
777  PP.EnterToken(Tok, /*IsReinject*/ true);
778  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
779                      /*IsReinject*/ true);
780  // Consume the previously pushed token.
781  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
782  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
783
784  FNContextRAII FnContext(*this, Ptr);
785  OMPDeclareSimdDeclAttr::BranchStateTy BS =
786      OMPDeclareSimdDeclAttr::BS_Undefined;
787  ExprResult Simdlen;
788  SmallVector<Expr *, 4> Uniforms;
789  SmallVector<Expr *, 4> Aligneds;
790  SmallVector<Expr *, 4> Alignments;
791  SmallVector<Expr *, 4> Linears;
792  SmallVector<unsigned, 4> LinModifiers;
793  SmallVector<Expr *, 4> Steps;
794  bool IsError =
795      parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
796                              Alignments, Linears, LinModifiers, Steps);
797  // Need to check for extra tokens.
798  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
799    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
800        << getOpenMPDirectiveName(OMPD_declare_simd);
801    while (Tok.isNot(tok::annot_pragma_openmp_end))
802      ConsumeAnyToken();
803  }
804  // Skip the last annot_pragma_openmp_end.
805  SourceLocation EndLoc = ConsumeAnnotationToken();
806  if (IsError)
807    return Ptr;
808  return Actions.ActOnOpenMPDeclareSimdDirective(
809      Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
810      LinModifiers, Steps, SourceRange(Loc, EndLoc));
811}
812
813/// Parse optional 'score' '(' <expr> ')' ':'.
814static ExprResult parseContextScore(Parser &P) {
815  ExprResult ScoreExpr;
816  Sema::OMPCtxStringType Buffer;
817  StringRef SelectorName =
818      P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
819  if (!SelectorName.equals("score"))
820    return ScoreExpr;
821  (void)P.ConsumeToken();
822  SourceLocation RLoc;
823  ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
824  // Parse ':'
825  if (P.getCurToken().is(tok::colon))
826    (void)P.ConsumeAnyToken();
827  else
828    P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon)
829        << "context selector score clause";
830  return ScoreExpr;
831}
832
833/// Parse context selector for 'implementation' selector set:
834/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
835/// ')'
836static void
837parseImplementationSelector(Parser &P, SourceLocation Loc,
838                            llvm::StringMap<SourceLocation> &UsedCtx,
839                            SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
840  const Token &Tok = P.getCurToken();
841  // Parse inner context selector set name, if any.
842  if (!Tok.is(tok::identifier)) {
843    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
844        << "implementation";
845    // Skip until either '}', ')', or end of directive.
846    while (!P.SkipUntil(tok::r_brace, tok::r_paren,
847                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
848      ;
849    return;
850  }
851  Sema::OMPCtxStringType Buffer;
852  StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
853  auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
854  if (!Res.second) {
855    // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
856    // Each trait-selector-name can only be specified once.
857    P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
858        << CtxSelectorName << "implementation";
859    P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
860        << CtxSelectorName;
861  }
862  OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
863  (void)P.ConsumeToken();
864  switch (CSKind) {
865  case OMP_CTX_vendor: {
866    // Parse '('.
867    BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
868    (void)T.expectAndConsume(diag::err_expected_lparen_after,
869                             CtxSelectorName.data());
870    ExprResult Score = parseContextScore(P);
871    llvm::UniqueVector<Sema::OMPCtxStringType> Vendors;
872    do {
873      // Parse <vendor>.
874      StringRef VendorName;
875      if (Tok.is(tok::identifier)) {
876        Buffer.clear();
877        VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
878        (void)P.ConsumeToken();
879        if (!VendorName.empty())
880          Vendors.insert(VendorName);
881      } else {
882        P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
883            << "vendor identifier"
884            << "vendor"
885            << "implementation";
886      }
887      if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
888        P.Diag(Tok, diag::err_expected_punc)
889            << (VendorName.empty() ? "vendor name" : VendorName);
890      }
891    } while (Tok.is(tok::identifier));
892    // Parse ')'.
893    (void)T.consumeClose();
894    if (!Vendors.empty())
895      Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
896    break;
897  }
898  case OMP_CTX_kind:
899  case OMP_CTX_unknown:
900    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
901        << "implementation";
902    // Skip until either '}', ')', or end of directive.
903    while (!P.SkipUntil(tok::r_brace, tok::r_paren,
904                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
905      ;
906    return;
907  }
908}
909
910/// Parse context selector for 'device' selector set:
911/// 'kind' '(' <kind> { ',' <kind> } ')'
912static void
913parseDeviceSelector(Parser &P, SourceLocation Loc,
914                    llvm::StringMap<SourceLocation> &UsedCtx,
915                    SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
916  const Token &Tok = P.getCurToken();
917  // Parse inner context selector set name, if any.
918  if (!Tok.is(tok::identifier)) {
919    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
920        << "device";
921    // Skip until either '}', ')', or end of directive.
922    while (!P.SkipUntil(tok::r_brace, tok::r_paren,
923                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
924      ;
925    return;
926  }
927  Sema::OMPCtxStringType Buffer;
928  StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
929  auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
930  if (!Res.second) {
931    // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
932    // Each trait-selector-name can only be specified once.
933    P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
934        << CtxSelectorName << "device";
935    P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
936        << CtxSelectorName;
937  }
938  OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
939  (void)P.ConsumeToken();
940  switch (CSKind) {
941  case OMP_CTX_kind: {
942    // Parse '('.
943    BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
944    (void)T.expectAndConsume(diag::err_expected_lparen_after,
945                             CtxSelectorName.data());
946    llvm::UniqueVector<Sema::OMPCtxStringType> Kinds;
947    do {
948      // Parse <kind>.
949      StringRef KindName;
950      if (Tok.is(tok::identifier)) {
951        Buffer.clear();
952        KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
953        SourceLocation SLoc = P.getCurToken().getLocation();
954        (void)P.ConsumeToken();
955        if (llvm::StringSwitch<bool>(KindName)
956                .Case("host", false)
957                .Case("nohost", false)
958                .Case("cpu", false)
959                .Case("gpu", false)
960                .Case("fpga", false)
961                .Default(true)) {
962          P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName;
963        } else {
964          Kinds.insert(KindName);
965        }
966      } else {
967        P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
968            << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'"
969            << "kind"
970            << "device";
971      }
972      if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
973        P.Diag(Tok, diag::err_expected_punc)
974            << (KindName.empty() ? "kind of device" : KindName);
975      }
976    } while (Tok.is(tok::identifier));
977    // Parse ')'.
978    (void)T.consumeClose();
979    if (!Kinds.empty())
980      Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds);
981    break;
982  }
983  case OMP_CTX_vendor:
984  case OMP_CTX_unknown:
985    P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
986        << "device";
987    // Skip until either '}', ')', or end of directive.
988    while (!P.SkipUntil(tok::r_brace, tok::r_paren,
989                        tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
990      ;
991    return;
992  }
993}
994
995/// Parses clauses for 'declare variant' directive.
996/// clause:
997/// <selector_set_name> '=' '{' <context_selectors> '}'
998/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
999bool Parser::parseOpenMPContextSelectors(
1000    SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
1001  llvm::StringMap<SourceLocation> UsedCtxSets;
1002  do {
1003    // Parse inner context selector set name.
1004    if (!Tok.is(tok::identifier)) {
1005      Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
1006          << getOpenMPClauseName(OMPC_match);
1007      return true;
1008    }
1009    Sema::OMPCtxStringType Buffer;
1010    StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
1011    auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation());
1012    if (!Res.second) {
1013      // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
1014      // Each trait-set-selector-name can only be specified once.
1015      Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use)
1016          << CtxSelectorSetName;
1017      Diag(Res.first->getValue(),
1018           diag::note_omp_declare_variant_ctx_set_used_here)
1019          << CtxSelectorSetName;
1020    }
1021    // Parse '='.
1022    (void)ConsumeToken();
1023    if (Tok.isNot(tok::equal)) {
1024      Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
1025          << CtxSelectorSetName;
1026      return true;
1027    }
1028    (void)ConsumeToken();
1029    // TBD: add parsing of known context selectors.
1030    // Unknown selector - just ignore it completely.
1031    {
1032      // Parse '{'.
1033      BalancedDelimiterTracker TBr(*this, tok::l_brace,
1034                                   tok::annot_pragma_openmp_end);
1035      if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
1036        return true;
1037      OpenMPContextSelectorSetKind CSSKind =
1038          getOpenMPContextSelectorSet(CtxSelectorSetName);
1039      llvm::StringMap<SourceLocation> UsedCtx;
1040      do {
1041        switch (CSSKind) {
1042        case OMP_CTX_SET_implementation:
1043          parseImplementationSelector(*this, Loc, UsedCtx, Data);
1044          break;
1045        case OMP_CTX_SET_device:
1046          parseDeviceSelector(*this, Loc, UsedCtx, Data);
1047          break;
1048        case OMP_CTX_SET_unknown:
1049          // Skip until either '}', ')', or end of directive.
1050          while (!SkipUntil(tok::r_brace, tok::r_paren,
1051                            tok::annot_pragma_openmp_end, StopBeforeMatch))
1052            ;
1053          break;
1054        }
1055        const Token PrevTok = Tok;
1056        if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
1057          Diag(Tok, diag::err_omp_expected_comma_brace)
1058              << (PrevTok.isAnnotation() ? "context selector trait"
1059                                         : PP.getSpelling(PrevTok));
1060      } while (Tok.is(tok::identifier));
1061      // Parse '}'.
1062      (void)TBr.consumeClose();
1063    }
1064    // Consume ','
1065    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
1066      (void)ExpectAndConsume(tok::comma);
1067  } while (Tok.isAnyIdentifier());
1068  return false;
1069}
1070
1071/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
1072void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1073                                           CachedTokens &Toks,
1074                                           SourceLocation Loc) {
1075  PP.EnterToken(Tok, /*IsReinject*/ true);
1076  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1077                      /*IsReinject*/ true);
1078  // Consume the previously pushed token.
1079  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1080  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1081
1082  FNContextRAII FnContext(*this, Ptr);
1083  // Parse function declaration id.
1084  SourceLocation RLoc;
1085  // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1086  // instead of MemberExprs.
1087  ExprResult AssociatedFunction;
1088  {
1089    // Do not mark function as is used to prevent its emission if this is the
1090    // only place where it is used.
1091    EnterExpressionEvaluationContext Unevaluated(
1092        Actions, Sema::ExpressionEvaluationContext::Unevaluated);
1093    AssociatedFunction = ParseOpenMPParensExpr(
1094        getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1095        /*IsAddressOfOperand=*/true);
1096  }
1097  if (!AssociatedFunction.isUsable()) {
1098    if (!Tok.is(tok::annot_pragma_openmp_end))
1099      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1100        ;
1101    // Skip the last annot_pragma_openmp_end.
1102    (void)ConsumeAnnotationToken();
1103    return;
1104  }
1105  Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1106      Actions.checkOpenMPDeclareVariantFunction(
1107          Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation()));
1108
1109  // Parse 'match'.
1110  OpenMPClauseKind CKind = Tok.isAnnotation()
1111                               ? OMPC_unknown
1112                               : getOpenMPClauseKind(PP.getSpelling(Tok));
1113  if (CKind != OMPC_match) {
1114    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1115        << getOpenMPClauseName(OMPC_match);
1116    while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
1117      ;
1118    // Skip the last annot_pragma_openmp_end.
1119    (void)ConsumeAnnotationToken();
1120    return;
1121  }
1122  (void)ConsumeToken();
1123  // Parse '('.
1124  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1125  if (T.expectAndConsume(diag::err_expected_lparen_after,
1126                         getOpenMPClauseName(OMPC_match))) {
1127    while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1128      ;
1129    // Skip the last annot_pragma_openmp_end.
1130    (void)ConsumeAnnotationToken();
1131    return;
1132  }
1133
1134  // Parse inner context selectors.
1135  SmallVector<Sema::OMPCtxSelectorData, 4> Data;
1136  if (!parseOpenMPContextSelectors(Loc, Data)) {
1137    // Parse ')'.
1138    (void)T.consumeClose();
1139    // Need to check for extra tokens.
1140    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1141      Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1142          << getOpenMPDirectiveName(OMPD_declare_variant);
1143    }
1144  }
1145
1146  // Skip last tokens.
1147  while (Tok.isNot(tok::annot_pragma_openmp_end))
1148    ConsumeAnyToken();
1149  if (DeclVarData.hasValue())
1150    Actions.ActOnOpenMPDeclareVariantDirective(
1151        DeclVarData.getValue().first, DeclVarData.getValue().second,
1152        SourceRange(Loc, Tok.getLocation()), Data);
1153  // Skip the last annot_pragma_openmp_end.
1154  (void)ConsumeAnnotationToken();
1155}
1156
1157/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1158///
1159///    default-clause:
1160///         'default' '(' 'none' | 'shared' ')
1161///
1162///    proc_bind-clause:
1163///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
1164///
1165///    device_type-clause:
1166///         'device_type' '(' 'host' | 'nohost' | 'any' )'
1167namespace {
1168  struct SimpleClauseData {
1169    unsigned Type;
1170    SourceLocation Loc;
1171    SourceLocation LOpen;
1172    SourceLocation TypeLoc;
1173    SourceLocation RLoc;
1174    SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1175                     SourceLocation TypeLoc, SourceLocation RLoc)
1176        : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1177  };
1178} // anonymous namespace
1179
1180static Optional<SimpleClauseData>
1181parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
1182  const Token &Tok = P.getCurToken();
1183  SourceLocation Loc = Tok.getLocation();
1184  SourceLocation LOpen = P.ConsumeToken();
1185  // Parse '('.
1186  BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1187  if (T.expectAndConsume(diag::err_expected_lparen_after,
1188                         getOpenMPClauseName(Kind)))
1189    return llvm::None;
1190
1191  unsigned Type = getOpenMPSimpleClauseType(
1192      Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok));
1193  SourceLocation TypeLoc = Tok.getLocation();
1194  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1195      Tok.isNot(tok::annot_pragma_openmp_end))
1196    P.ConsumeAnyToken();
1197
1198  // Parse ')'.
1199  SourceLocation RLoc = Tok.getLocation();
1200  if (!T.consumeClose())
1201    RLoc = T.getCloseLocation();
1202
1203  return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1204}
1205
1206Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
1207  // OpenMP 4.5 syntax with list of entities.
1208  Sema::NamedDeclSetType SameDirectiveDecls;
1209  SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
1210                         NamedDecl *>,
1211              4>
1212      DeclareTargetDecls;
1213  OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
1214  SourceLocation DeviceTypeLoc;
1215  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1216    OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1217    if (Tok.is(tok::identifier)) {
1218      IdentifierInfo *II = Tok.getIdentifierInfo();
1219      StringRef ClauseName = II->getName();
1220      bool IsDeviceTypeClause =
1221          getLangOpts().OpenMP >= 50 &&
1222          getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1223      // Parse 'to|link|device_type' clauses.
1224      if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
1225          !IsDeviceTypeClause) {
1226        Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1227            << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
1228        break;
1229      }
1230      // Parse 'device_type' clause and go to next clause if any.
1231      if (IsDeviceTypeClause) {
1232        Optional<SimpleClauseData> DevTypeData =
1233            parseOpenMPSimpleClause(*this, OMPC_device_type);
1234        if (DevTypeData.hasValue()) {
1235          if (DeviceTypeLoc.isValid()) {
1236            // We already saw another device_type clause, diagnose it.
1237            Diag(DevTypeData.getValue().Loc,
1238                 diag::warn_omp_more_one_device_type_clause);
1239          }
1240          switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
1241          case OMPC_DEVICE_TYPE_any:
1242            DT = OMPDeclareTargetDeclAttr::DT_Any;
1243            break;
1244          case OMPC_DEVICE_TYPE_host:
1245            DT = OMPDeclareTargetDeclAttr::DT_Host;
1246            break;
1247          case OMPC_DEVICE_TYPE_nohost:
1248            DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1249            break;
1250          case OMPC_DEVICE_TYPE_unknown:
1251            llvm_unreachable("Unexpected device_type");
1252          }
1253          DeviceTypeLoc = DevTypeData.getValue().Loc;
1254        }
1255        continue;
1256      }
1257      ConsumeToken();
1258    }
1259    auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
1260                          CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
1261      NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
1262          getCurScope(), SS, NameInfo, SameDirectiveDecls);
1263      if (ND)
1264        DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
1265    };
1266    if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1267                                 /*AllowScopeSpecifier=*/true))
1268      break;
1269
1270    // Consume optional ','.
1271    if (Tok.is(tok::comma))
1272      ConsumeToken();
1273  }
1274  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1275  ConsumeAnyToken();
1276  for (auto &MTLocDecl : DeclareTargetDecls) {
1277    OMPDeclareTargetDeclAttr::MapTypeTy MT;
1278    SourceLocation Loc;
1279    NamedDecl *ND;
1280    std::tie(MT, Loc, ND) = MTLocDecl;
1281    // device_type clause is applied only to functions.
1282    Actions.ActOnOpenMPDeclareTargetName(
1283        ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
1284  }
1285  SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
1286                               SameDirectiveDecls.end());
1287  if (Decls.empty())
1288    return DeclGroupPtrTy();
1289  return Actions.BuildDeclaratorGroup(Decls);
1290}
1291
1292void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
1293                                               SourceLocation DTLoc) {
1294  if (DKind != OMPD_end_declare_target) {
1295    Diag(Tok, diag::err_expected_end_declare_target);
1296    Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
1297    return;
1298  }
1299  ConsumeAnyToken();
1300  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1301    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1302        << getOpenMPDirectiveName(OMPD_end_declare_target);
1303    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1304  }
1305  // Skip the last annot_pragma_openmp_end.
1306  ConsumeAnyToken();
1307}
1308
1309/// Parsing of declarative OpenMP directives.
1310///
1311///       threadprivate-directive:
1312///         annot_pragma_openmp 'threadprivate' simple-variable-list
1313///         annot_pragma_openmp_end
1314///
1315///       allocate-directive:
1316///         annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
1317///         annot_pragma_openmp_end
1318///
1319///       declare-reduction-directive:
1320///        annot_pragma_openmp 'declare' 'reduction' [...]
1321///        annot_pragma_openmp_end
1322///
1323///       declare-mapper-directive:
1324///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1325///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
1326///         annot_pragma_openmp_end
1327///
1328///       declare-simd-directive:
1329///         annot_pragma_openmp 'declare simd' {<clause> [,]}
1330///         annot_pragma_openmp_end
1331///         <function declaration/definition>
1332///
1333///       requires directive:
1334///         annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
1335///         annot_pragma_openmp_end
1336///
1337Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1338    AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
1339    DeclSpec::TST TagType, Decl *Tag) {
1340  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1341  ParsingOpenMPDirectiveRAII DirScope(*this);
1342  ParenBraceBracketBalancer BalancerRAIIObj(*this);
1343
1344  SourceLocation Loc;
1345  OpenMPDirectiveKind DKind;
1346  if (Delayed) {
1347    TentativeParsingAction TPA(*this);
1348    Loc = ConsumeAnnotationToken();
1349    DKind = parseOpenMPDirectiveKind(*this);
1350    if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1351      // Need to delay parsing until completion of the parent class.
1352      TPA.Revert();
1353      CachedTokens Toks;
1354      unsigned Cnt = 1;
1355      Toks.push_back(Tok);
1356      while (Cnt && Tok.isNot(tok::eof)) {
1357        (void)ConsumeAnyToken();
1358        if (Tok.is(tok::annot_pragma_openmp))
1359          ++Cnt;
1360        else if (Tok.is(tok::annot_pragma_openmp_end))
1361          --Cnt;
1362        Toks.push_back(Tok);
1363      }
1364      // Skip last annot_pragma_openmp_end.
1365      if (Cnt == 0)
1366        (void)ConsumeAnyToken();
1367      auto *LP = new LateParsedPragma(this, AS);
1368      LP->takeToks(Toks);
1369      getCurrentClass().LateParsedDeclarations.push_back(LP);
1370      return nullptr;
1371    }
1372    TPA.Commit();
1373  } else {
1374    Loc = ConsumeAnnotationToken();
1375    DKind = parseOpenMPDirectiveKind(*this);
1376  }
1377
1378  switch (DKind) {
1379  case OMPD_threadprivate: {
1380    ConsumeToken();
1381    DeclDirectiveListParserHelper Helper(this, DKind);
1382    if (!ParseOpenMPSimpleVarList(DKind, Helper,
1383                                  /*AllowScopeSpecifier=*/true)) {
1384      // The last seen token is annot_pragma_openmp_end - need to check for
1385      // extra tokens.
1386      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1387        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1388            << getOpenMPDirectiveName(DKind);
1389        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1390      }
1391      // Skip the last annot_pragma_openmp_end.
1392      ConsumeAnnotationToken();
1393      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
1394                                                       Helper.getIdentifiers());
1395    }
1396    break;
1397  }
1398  case OMPD_allocate: {
1399    ConsumeToken();
1400    DeclDirectiveListParserHelper Helper(this, DKind);
1401    if (!ParseOpenMPSimpleVarList(DKind, Helper,
1402                                  /*AllowScopeSpecifier=*/true)) {
1403      SmallVector<OMPClause *, 1> Clauses;
1404      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1405        SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1406                    OMPC_unknown + 1>
1407            FirstClauses(OMPC_unknown + 1);
1408        while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1409          OpenMPClauseKind CKind =
1410              Tok.isAnnotation() ? OMPC_unknown
1411                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
1412          Actions.StartOpenMPClause(CKind);
1413          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1414                                                !FirstClauses[CKind].getInt());
1415          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1416                    StopBeforeMatch);
1417          FirstClauses[CKind].setInt(true);
1418          if (Clause != nullptr)
1419            Clauses.push_back(Clause);
1420          if (Tok.is(tok::annot_pragma_openmp_end)) {
1421            Actions.EndOpenMPClause();
1422            break;
1423          }
1424          // Skip ',' if any.
1425          if (Tok.is(tok::comma))
1426            ConsumeToken();
1427          Actions.EndOpenMPClause();
1428        }
1429        // The last seen token is annot_pragma_openmp_end - need to check for
1430        // extra tokens.
1431        if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1432          Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1433              << getOpenMPDirectiveName(DKind);
1434          SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1435        }
1436      }
1437      // Skip the last annot_pragma_openmp_end.
1438      ConsumeAnnotationToken();
1439      return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
1440                                                  Clauses);
1441    }
1442    break;
1443  }
1444  case OMPD_requires: {
1445    SourceLocation StartLoc = ConsumeToken();
1446    SmallVector<OMPClause *, 5> Clauses;
1447    SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
1448    FirstClauses(OMPC_unknown + 1);
1449    if (Tok.is(tok::annot_pragma_openmp_end)) {
1450      Diag(Tok, diag::err_omp_expected_clause)
1451          << getOpenMPDirectiveName(OMPD_requires);
1452      break;
1453    }
1454    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1455      OpenMPClauseKind CKind = Tok.isAnnotation()
1456                                   ? OMPC_unknown
1457                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
1458      Actions.StartOpenMPClause(CKind);
1459      OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
1460                                            !FirstClauses[CKind].getInt());
1461      SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1462                StopBeforeMatch);
1463      FirstClauses[CKind].setInt(true);
1464      if (Clause != nullptr)
1465        Clauses.push_back(Clause);
1466      if (Tok.is(tok::annot_pragma_openmp_end)) {
1467        Actions.EndOpenMPClause();
1468        break;
1469      }
1470      // Skip ',' if any.
1471      if (Tok.is(tok::comma))
1472        ConsumeToken();
1473      Actions.EndOpenMPClause();
1474    }
1475    // Consume final annot_pragma_openmp_end
1476    if (Clauses.size() == 0) {
1477      Diag(Tok, diag::err_omp_expected_clause)
1478          << getOpenMPDirectiveName(OMPD_requires);
1479      ConsumeAnnotationToken();
1480      return nullptr;
1481    }
1482    ConsumeAnnotationToken();
1483    return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
1484  }
1485  case OMPD_declare_reduction:
1486    ConsumeToken();
1487    if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
1488      // The last seen token is annot_pragma_openmp_end - need to check for
1489      // extra tokens.
1490      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1491        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1492            << getOpenMPDirectiveName(OMPD_declare_reduction);
1493        while (Tok.isNot(tok::annot_pragma_openmp_end))
1494          ConsumeAnyToken();
1495      }
1496      // Skip the last annot_pragma_openmp_end.
1497      ConsumeAnnotationToken();
1498      return Res;
1499    }
1500    break;
1501  case OMPD_declare_mapper: {
1502    ConsumeToken();
1503    if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1504      // Skip the last annot_pragma_openmp_end.
1505      ConsumeAnnotationToken();
1506      return Res;
1507    }
1508    break;
1509  }
1510  case OMPD_declare_variant:
1511  case OMPD_declare_simd: {
1512    // The syntax is:
1513    // { #pragma omp declare {simd|variant} }
1514    // <function-declaration-or-definition>
1515    //
1516    CachedTokens Toks;
1517    Toks.push_back(Tok);
1518    ConsumeToken();
1519    while(Tok.isNot(tok::annot_pragma_openmp_end)) {
1520      Toks.push_back(Tok);
1521      ConsumeAnyToken();
1522    }
1523    Toks.push_back(Tok);
1524    ConsumeAnyToken();
1525
1526    DeclGroupPtrTy Ptr;
1527    if (Tok.is(tok::annot_pragma_openmp)) {
1528      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
1529                                                       TagType, Tag);
1530    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1531      // Here we expect to see some function declaration.
1532      if (AS == AS_none) {
1533        assert(TagType == DeclSpec::TST_unspecified);
1534        MaybeParseCXX11Attributes(Attrs);
1535        ParsingDeclSpec PDS(*this);
1536        Ptr = ParseExternalDeclaration(Attrs, &PDS);
1537      } else {
1538        Ptr =
1539            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1540      }
1541    }
1542    if (!Ptr) {
1543      Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
1544          << (DKind == OMPD_declare_simd ? 0 : 1);
1545      return DeclGroupPtrTy();
1546    }
1547    if (DKind == OMPD_declare_simd)
1548      return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1549    assert(DKind == OMPD_declare_variant &&
1550           "Expected declare variant directive only");
1551    ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
1552    return Ptr;
1553  }
1554  case OMPD_declare_target: {
1555    SourceLocation DTLoc = ConsumeAnyToken();
1556    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1557      return ParseOMPDeclareTargetClauses();
1558    }
1559
1560    // Skip the last annot_pragma_openmp_end.
1561    ConsumeAnyToken();
1562
1563    if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1564      return DeclGroupPtrTy();
1565
1566    llvm::SmallVector<Decl *, 4>  Decls;
1567    DKind = parseOpenMPDirectiveKind(*this);
1568    while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1569           Tok.isNot(tok::r_brace)) {
1570      DeclGroupPtrTy Ptr;
1571      // Here we expect to see some function declaration.
1572      if (AS == AS_none) {
1573        assert(TagType == DeclSpec::TST_unspecified);
1574        MaybeParseCXX11Attributes(Attrs);
1575        ParsingDeclSpec PDS(*this);
1576        Ptr = ParseExternalDeclaration(Attrs, &PDS);
1577      } else {
1578        Ptr =
1579            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1580      }
1581      if (Ptr) {
1582        DeclGroupRef Ref = Ptr.get();
1583        Decls.append(Ref.begin(), Ref.end());
1584      }
1585      if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
1586        TentativeParsingAction TPA(*this);
1587        ConsumeAnnotationToken();
1588        DKind = parseOpenMPDirectiveKind(*this);
1589        if (DKind != OMPD_end_declare_target)
1590          TPA.Revert();
1591        else
1592          TPA.Commit();
1593      }
1594    }
1595
1596    ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1597    Actions.ActOnFinishOpenMPDeclareTargetDirective();
1598    return Actions.BuildDeclaratorGroup(Decls);
1599  }
1600  case OMPD_unknown:
1601    Diag(Tok, diag::err_omp_unknown_directive);
1602    break;
1603  case OMPD_parallel:
1604  case OMPD_simd:
1605  case OMPD_task:
1606  case OMPD_taskyield:
1607  case OMPD_barrier:
1608  case OMPD_taskwait:
1609  case OMPD_taskgroup:
1610  case OMPD_flush:
1611  case OMPD_for:
1612  case OMPD_for_simd:
1613  case OMPD_sections:
1614  case OMPD_section:
1615  case OMPD_single:
1616  case OMPD_master:
1617  case OMPD_ordered:
1618  case OMPD_critical:
1619  case OMPD_parallel_for:
1620  case OMPD_parallel_for_simd:
1621  case OMPD_parallel_sections:
1622  case OMPD_parallel_master:
1623  case OMPD_atomic:
1624  case OMPD_target:
1625  case OMPD_teams:
1626  case OMPD_cancellation_point:
1627  case OMPD_cancel:
1628  case OMPD_target_data:
1629  case OMPD_target_enter_data:
1630  case OMPD_target_exit_data:
1631  case OMPD_target_parallel:
1632  case OMPD_target_parallel_for:
1633  case OMPD_taskloop:
1634  case OMPD_taskloop_simd:
1635  case OMPD_master_taskloop:
1636  case OMPD_master_taskloop_simd:
1637  case OMPD_parallel_master_taskloop:
1638  case OMPD_parallel_master_taskloop_simd:
1639  case OMPD_distribute:
1640  case OMPD_end_declare_target:
1641  case OMPD_target_update:
1642  case OMPD_distribute_parallel_for:
1643  case OMPD_distribute_parallel_for_simd:
1644  case OMPD_distribute_simd:
1645  case OMPD_target_parallel_for_simd:
1646  case OMPD_target_simd:
1647  case OMPD_teams_distribute:
1648  case OMPD_teams_distribute_simd:
1649  case OMPD_teams_distribute_parallel_for_simd:
1650  case OMPD_teams_distribute_parallel_for:
1651  case OMPD_target_teams:
1652  case OMPD_target_teams_distribute:
1653  case OMPD_target_teams_distribute_parallel_for:
1654  case OMPD_target_teams_distribute_parallel_for_simd:
1655  case OMPD_target_teams_distribute_simd:
1656    Diag(Tok, diag::err_omp_unexpected_directive)
1657        << 1 << getOpenMPDirectiveName(DKind);
1658    break;
1659  }
1660  while (Tok.isNot(tok::annot_pragma_openmp_end))
1661    ConsumeAnyToken();
1662  ConsumeAnyToken();
1663  return nullptr;
1664}
1665
1666/// Parsing of declarative or executable OpenMP directives.
1667///
1668///       threadprivate-directive:
1669///         annot_pragma_openmp 'threadprivate' simple-variable-list
1670///         annot_pragma_openmp_end
1671///
1672///       allocate-directive:
1673///         annot_pragma_openmp 'allocate' simple-variable-list
1674///         annot_pragma_openmp_end
1675///
1676///       declare-reduction-directive:
1677///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
1678///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
1679///         ('omp_priv' '=' <expression>|<function_call>) ')']
1680///         annot_pragma_openmp_end
1681///
1682///       declare-mapper-directive:
1683///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1684///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
1685///         annot_pragma_openmp_end
1686///
1687///       executable-directive:
1688///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
1689///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
1690///         'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
1691///         'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
1692///         'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
1693///         data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
1694///         'master taskloop' | 'master taskloop simd' | 'parallel master
1695///         taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
1696///         enter data' | 'target exit data' | 'target parallel' | 'target
1697///         parallel for' | 'target update' | 'distribute parallel for' |
1698///         'distribute paralle for simd' | 'distribute simd' | 'target parallel
1699///         for simd' | 'target simd' | 'teams distribute' | 'teams distribute
1700///         simd' | 'teams distribute parallel for simd' | 'teams distribute
1701///         parallel for' | 'target teams' | 'target teams distribute' | 'target
1702///         teams distribute parallel for' | 'target teams distribute parallel
1703///         for simd' | 'target teams distribute simd' {clause}
1704///         annot_pragma_openmp_end
1705///
1706StmtResult
1707Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1708  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1709  ParsingOpenMPDirectiveRAII DirScope(*this);
1710  ParenBraceBracketBalancer BalancerRAIIObj(*this);
1711  SmallVector<OMPClause *, 5> Clauses;
1712  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
1713  FirstClauses(OMPC_unknown + 1);
1714  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
1715                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
1716  SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
1717  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
1718  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
1719  // Name of critical directive.
1720  DeclarationNameInfo DirName;
1721  StmtResult Directive = StmtError();
1722  bool HasAssociatedStatement = true;
1723  bool FlushHasClause = false;
1724
1725  switch (DKind) {
1726  case OMPD_threadprivate: {
1727    // FIXME: Should this be permitted in C++?
1728    if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1729        ParsedStmtContext()) {
1730      Diag(Tok, diag::err_omp_immediate_directive)
1731          << getOpenMPDirectiveName(DKind) << 0;
1732    }
1733    ConsumeToken();
1734    DeclDirectiveListParserHelper Helper(this, DKind);
1735    if (!ParseOpenMPSimpleVarList(DKind, Helper,
1736                                  /*AllowScopeSpecifier=*/false)) {
1737      // The last seen token is annot_pragma_openmp_end - need to check for
1738      // extra tokens.
1739      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1740        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1741            << getOpenMPDirectiveName(DKind);
1742        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1743      }
1744      DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
1745          Loc, Helper.getIdentifiers());
1746      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1747    }
1748    SkipUntil(tok::annot_pragma_openmp_end);
1749    break;
1750  }
1751  case OMPD_allocate: {
1752    // FIXME: Should this be permitted in C++?
1753    if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1754        ParsedStmtContext()) {
1755      Diag(Tok, diag::err_omp_immediate_directive)
1756          << getOpenMPDirectiveName(DKind) << 0;
1757    }
1758    ConsumeToken();
1759    DeclDirectiveListParserHelper Helper(this, DKind);
1760    if (!ParseOpenMPSimpleVarList(DKind, Helper,
1761                                  /*AllowScopeSpecifier=*/false)) {
1762      SmallVector<OMPClause *, 1> Clauses;
1763      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1764        SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1765                    OMPC_unknown + 1>
1766            FirstClauses(OMPC_unknown + 1);
1767        while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1768          OpenMPClauseKind CKind =
1769              Tok.isAnnotation() ? OMPC_unknown
1770                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
1771          Actions.StartOpenMPClause(CKind);
1772          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1773                                                !FirstClauses[CKind].getInt());
1774          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1775                    StopBeforeMatch);
1776          FirstClauses[CKind].setInt(true);
1777          if (Clause != nullptr)
1778            Clauses.push_back(Clause);
1779          if (Tok.is(tok::annot_pragma_openmp_end)) {
1780            Actions.EndOpenMPClause();
1781            break;
1782          }
1783          // Skip ',' if any.
1784          if (Tok.is(tok::comma))
1785            ConsumeToken();
1786          Actions.EndOpenMPClause();
1787        }
1788        // The last seen token is annot_pragma_openmp_end - need to check for
1789        // extra tokens.
1790        if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1791          Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1792              << getOpenMPDirectiveName(DKind);
1793          SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1794        }
1795      }
1796      DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
1797          Loc, Helper.getIdentifiers(), Clauses);
1798      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1799    }
1800    SkipUntil(tok::annot_pragma_openmp_end);
1801    break;
1802  }
1803  case OMPD_declare_reduction:
1804    ConsumeToken();
1805    if (DeclGroupPtrTy Res =
1806            ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
1807      // The last seen token is annot_pragma_openmp_end - need to check for
1808      // extra tokens.
1809      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1810        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1811            << getOpenMPDirectiveName(OMPD_declare_reduction);
1812        while (Tok.isNot(tok::annot_pragma_openmp_end))
1813          ConsumeAnyToken();
1814      }
1815      ConsumeAnyToken();
1816      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1817    } else {
1818      SkipUntil(tok::annot_pragma_openmp_end);
1819    }
1820    break;
1821  case OMPD_declare_mapper: {
1822    ConsumeToken();
1823    if (DeclGroupPtrTy Res =
1824            ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
1825      // Skip the last annot_pragma_openmp_end.
1826      ConsumeAnnotationToken();
1827      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1828    } else {
1829      SkipUntil(tok::annot_pragma_openmp_end);
1830    }
1831    break;
1832  }
1833  case OMPD_flush:
1834    if (PP.LookAhead(0).is(tok::l_paren)) {
1835      FlushHasClause = true;
1836      // Push copy of the current token back to stream to properly parse
1837      // pseudo-clause OMPFlushClause.
1838      PP.EnterToken(Tok, /*IsReinject*/ true);
1839    }
1840    LLVM_FALLTHROUGH;
1841  case OMPD_taskyield:
1842  case OMPD_barrier:
1843  case OMPD_taskwait:
1844  case OMPD_cancellation_point:
1845  case OMPD_cancel:
1846  case OMPD_target_enter_data:
1847  case OMPD_target_exit_data:
1848  case OMPD_target_update:
1849    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1850        ParsedStmtContext()) {
1851      Diag(Tok, diag::err_omp_immediate_directive)
1852          << getOpenMPDirectiveName(DKind) << 0;
1853    }
1854    HasAssociatedStatement = false;
1855    // Fall through for further analysis.
1856    LLVM_FALLTHROUGH;
1857  case OMPD_parallel:
1858  case OMPD_simd:
1859  case OMPD_for:
1860  case OMPD_for_simd:
1861  case OMPD_sections:
1862  case OMPD_single:
1863  case OMPD_section:
1864  case OMPD_master:
1865  case OMPD_critical:
1866  case OMPD_parallel_for:
1867  case OMPD_parallel_for_simd:
1868  case OMPD_parallel_sections:
1869  case OMPD_parallel_master:
1870  case OMPD_task:
1871  case OMPD_ordered:
1872  case OMPD_atomic:
1873  case OMPD_target:
1874  case OMPD_teams:
1875  case OMPD_taskgroup:
1876  case OMPD_target_data:
1877  case OMPD_target_parallel:
1878  case OMPD_target_parallel_for:
1879  case OMPD_taskloop:
1880  case OMPD_taskloop_simd:
1881  case OMPD_master_taskloop:
1882  case OMPD_master_taskloop_simd:
1883  case OMPD_parallel_master_taskloop:
1884  case OMPD_parallel_master_taskloop_simd:
1885  case OMPD_distribute:
1886  case OMPD_distribute_parallel_for:
1887  case OMPD_distribute_parallel_for_simd:
1888  case OMPD_distribute_simd:
1889  case OMPD_target_parallel_for_simd:
1890  case OMPD_target_simd:
1891  case OMPD_teams_distribute:
1892  case OMPD_teams_distribute_simd:
1893  case OMPD_teams_distribute_parallel_for_simd:
1894  case OMPD_teams_distribute_parallel_for:
1895  case OMPD_target_teams:
1896  case OMPD_target_teams_distribute:
1897  case OMPD_target_teams_distribute_parallel_for:
1898  case OMPD_target_teams_distribute_parallel_for_simd:
1899  case OMPD_target_teams_distribute_simd: {
1900    ConsumeToken();
1901    // Parse directive name of the 'critical' directive if any.
1902    if (DKind == OMPD_critical) {
1903      BalancedDelimiterTracker T(*this, tok::l_paren,
1904                                 tok::annot_pragma_openmp_end);
1905      if (!T.consumeOpen()) {
1906        if (Tok.isAnyIdentifier()) {
1907          DirName =
1908              DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1909          ConsumeAnyToken();
1910        } else {
1911          Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1912        }
1913        T.consumeClose();
1914      }
1915    } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1916      CancelRegion = parseOpenMPDirectiveKind(*this);
1917      if (Tok.isNot(tok::annot_pragma_openmp_end))
1918        ConsumeToken();
1919    }
1920
1921    if (isOpenMPLoopDirective(DKind))
1922      ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1923    if (isOpenMPSimdDirective(DKind))
1924      ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1925    ParseScope OMPDirectiveScope(this, ScopeFlags);
1926    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1927
1928    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1929      OpenMPClauseKind CKind =
1930          Tok.isAnnotation()
1931              ? OMPC_unknown
1932              : FlushHasClause ? OMPC_flush
1933                               : getOpenMPClauseKind(PP.getSpelling(Tok));
1934      Actions.StartOpenMPClause(CKind);
1935      FlushHasClause = false;
1936      OMPClause *Clause =
1937          ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1938      FirstClauses[CKind].setInt(true);
1939      if (Clause) {
1940        FirstClauses[CKind].setPointer(Clause);
1941        Clauses.push_back(Clause);
1942      }
1943
1944      // Skip ',' if any.
1945      if (Tok.is(tok::comma))
1946        ConsumeToken();
1947      Actions.EndOpenMPClause();
1948    }
1949    // End location of the directive.
1950    EndLoc = Tok.getLocation();
1951    // Consume final annot_pragma_openmp_end.
1952    ConsumeAnnotationToken();
1953
1954    // OpenMP [2.13.8, ordered Construct, Syntax]
1955    // If the depend clause is specified, the ordered construct is a stand-alone
1956    // directive.
1957    if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1958      if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1959          ParsedStmtContext()) {
1960        Diag(Loc, diag::err_omp_immediate_directive)
1961            << getOpenMPDirectiveName(DKind) << 1
1962            << getOpenMPClauseName(OMPC_depend);
1963      }
1964      HasAssociatedStatement = false;
1965    }
1966
1967    StmtResult AssociatedStmt;
1968    if (HasAssociatedStatement) {
1969      // The body is a block scope like in Lambdas and Blocks.
1970      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1971      // FIXME: We create a bogus CompoundStmt scope to hold the contents of
1972      // the captured region. Code elsewhere assumes that any FunctionScopeInfo
1973      // should have at least one compound statement scope within it.
1974      AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
1975      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1976    } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1977               DKind == OMPD_target_exit_data) {
1978      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1979      AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
1980                        Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
1981                                                  /*isStmtExpr=*/false));
1982      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1983    }
1984    Directive = Actions.ActOnOpenMPExecutableDirective(
1985        DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1986        EndLoc);
1987
1988    // Exit scope.
1989    Actions.EndOpenMPDSABlock(Directive.get());
1990    OMPDirectiveScope.Exit();
1991    break;
1992  }
1993  case OMPD_declare_simd:
1994  case OMPD_declare_target:
1995  case OMPD_end_declare_target:
1996  case OMPD_requires:
1997  case OMPD_declare_variant:
1998    Diag(Tok, diag::err_omp_unexpected_directive)
1999        << 1 << getOpenMPDirectiveName(DKind);
2000    SkipUntil(tok::annot_pragma_openmp_end);
2001    break;
2002  case OMPD_unknown:
2003    Diag(Tok, diag::err_omp_unknown_directive);
2004    SkipUntil(tok::annot_pragma_openmp_end);
2005    break;
2006  }
2007  return Directive;
2008}
2009
2010// Parses simple list:
2011//   simple-variable-list:
2012//         '(' id-expression {, id-expression} ')'
2013//
2014bool Parser::ParseOpenMPSimpleVarList(
2015    OpenMPDirectiveKind Kind,
2016    const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
2017        Callback,
2018    bool AllowScopeSpecifier) {
2019  // Parse '('.
2020  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2021  if (T.expectAndConsume(diag::err_expected_lparen_after,
2022                         getOpenMPDirectiveName(Kind).data()))
2023    return true;
2024  bool IsCorrect = true;
2025  bool NoIdentIsFound = true;
2026
2027  // Read tokens while ')' or annot_pragma_openmp_end is not found.
2028  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2029    CXXScopeSpec SS;
2030    UnqualifiedId Name;
2031    // Read var name.
2032    Token PrevTok = Tok;
2033    NoIdentIsFound = false;
2034
2035    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2036        ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
2037      IsCorrect = false;
2038      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2039                StopBeforeMatch);
2040    } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
2041                                  nullptr, Name)) {
2042      IsCorrect = false;
2043      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2044                StopBeforeMatch);
2045    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2046               Tok.isNot(tok::annot_pragma_openmp_end)) {
2047      IsCorrect = false;
2048      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2049                StopBeforeMatch);
2050      Diag(PrevTok.getLocation(), diag::err_expected)
2051          << tok::identifier
2052          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2053    } else {
2054      Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2055    }
2056    // Consume ','.
2057    if (Tok.is(tok::comma)) {
2058      ConsumeToken();
2059    }
2060  }
2061
2062  if (NoIdentIsFound) {
2063    Diag(Tok, diag::err_expected) << tok::identifier;
2064    IsCorrect = false;
2065  }
2066
2067  // Parse ')'.
2068  IsCorrect = !T.consumeClose() && IsCorrect;
2069
2070  return !IsCorrect;
2071}
2072
2073/// Parsing of OpenMP clauses.
2074///
2075///    clause:
2076///       if-clause | final-clause | num_threads-clause | safelen-clause |
2077///       default-clause | private-clause | firstprivate-clause | shared-clause
2078///       | linear-clause | aligned-clause | collapse-clause |
2079///       lastprivate-clause | reduction-clause | proc_bind-clause |
2080///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
2081///       mergeable-clause | flush-clause | read-clause | write-clause |
2082///       update-clause | capture-clause | seq_cst-clause | device-clause |
2083///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
2084///       thread_limit-clause | priority-clause | grainsize-clause |
2085///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
2086///       from-clause | is_device_ptr-clause | task_reduction-clause |
2087///       in_reduction-clause | allocator-clause | allocate-clause
2088///
2089OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
2090                                     OpenMPClauseKind CKind, bool FirstClause) {
2091  OMPClause *Clause = nullptr;
2092  bool ErrorFound = false;
2093  bool WrongDirective = false;
2094  // Check if clause is allowed for the given directive.
2095  if (CKind != OMPC_unknown &&
2096      !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
2097    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
2098                                               << getOpenMPDirectiveName(DKind);
2099    ErrorFound = true;
2100    WrongDirective = true;
2101  }
2102
2103  switch (CKind) {
2104  case OMPC_final:
2105  case OMPC_num_threads:
2106  case OMPC_safelen:
2107  case OMPC_simdlen:
2108  case OMPC_collapse:
2109  case OMPC_ordered:
2110  case OMPC_device:
2111  case OMPC_num_teams:
2112  case OMPC_thread_limit:
2113  case OMPC_priority:
2114  case OMPC_grainsize:
2115  case OMPC_num_tasks:
2116  case OMPC_hint:
2117  case OMPC_allocator:
2118    // OpenMP [2.5, Restrictions]
2119    //  At most one num_threads clause can appear on the directive.
2120    // OpenMP [2.8.1, simd construct, Restrictions]
2121    //  Only one safelen  clause can appear on a simd directive.
2122    //  Only one simdlen  clause can appear on a simd directive.
2123    //  Only one collapse clause can appear on a simd directive.
2124    // OpenMP [2.9.1, target data construct, Restrictions]
2125    //  At most one device clause can appear on the directive.
2126    // OpenMP [2.11.1, task Construct, Restrictions]
2127    //  At most one if clause can appear on the directive.
2128    //  At most one final clause can appear on the directive.
2129    // OpenMP [teams Construct, Restrictions]
2130    //  At most one num_teams clause can appear on the directive.
2131    //  At most one thread_limit clause can appear on the directive.
2132    // OpenMP [2.9.1, task Construct, Restrictions]
2133    // At most one priority clause can appear on the directive.
2134    // OpenMP [2.9.2, taskloop Construct, Restrictions]
2135    // At most one grainsize clause can appear on the directive.
2136    // OpenMP [2.9.2, taskloop Construct, Restrictions]
2137    // At most one num_tasks clause can appear on the directive.
2138    // OpenMP [2.11.3, allocate Directive, Restrictions]
2139    // At most one allocator clause can appear on the directive.
2140    if (!FirstClause) {
2141      Diag(Tok, diag::err_omp_more_one_clause)
2142          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2143      ErrorFound = true;
2144    }
2145
2146    if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
2147      Clause = ParseOpenMPClause(CKind, WrongDirective);
2148    else
2149      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
2150    break;
2151  case OMPC_default:
2152  case OMPC_proc_bind:
2153  case OMPC_atomic_default_mem_order:
2154    // OpenMP [2.14.3.1, Restrictions]
2155    //  Only a single default clause may be specified on a parallel, task or
2156    //  teams directive.
2157    // OpenMP [2.5, parallel Construct, Restrictions]
2158    //  At most one proc_bind clause can appear on the directive.
2159    // OpenMP [5.0, Requires directive, Restrictions]
2160    //  At most one atomic_default_mem_order clause can appear
2161    //  on the directive
2162    if (!FirstClause) {
2163      Diag(Tok, diag::err_omp_more_one_clause)
2164          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2165      ErrorFound = true;
2166    }
2167
2168    Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
2169    break;
2170  case OMPC_schedule:
2171  case OMPC_dist_schedule:
2172  case OMPC_defaultmap:
2173    // OpenMP [2.7.1, Restrictions, p. 3]
2174    //  Only one schedule clause can appear on a loop directive.
2175    // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
2176    //  At most one defaultmap clause can appear on the directive.
2177    if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
2178        !FirstClause) {
2179      Diag(Tok, diag::err_omp_more_one_clause)
2180          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2181      ErrorFound = true;
2182    }
2183    LLVM_FALLTHROUGH;
2184  case OMPC_if:
2185    Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
2186    break;
2187  case OMPC_nowait:
2188  case OMPC_untied:
2189  case OMPC_mergeable:
2190  case OMPC_read:
2191  case OMPC_write:
2192  case OMPC_update:
2193  case OMPC_capture:
2194  case OMPC_seq_cst:
2195  case OMPC_threads:
2196  case OMPC_simd:
2197  case OMPC_nogroup:
2198  case OMPC_unified_address:
2199  case OMPC_unified_shared_memory:
2200  case OMPC_reverse_offload:
2201  case OMPC_dynamic_allocators:
2202    // OpenMP [2.7.1, Restrictions, p. 9]
2203    //  Only one ordered clause can appear on a loop directive.
2204    // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
2205    //  Only one nowait clause can appear on a for directive.
2206    // OpenMP [5.0, Requires directive, Restrictions]
2207    //   Each of the requires clauses can appear at most once on the directive.
2208    if (!FirstClause) {
2209      Diag(Tok, diag::err_omp_more_one_clause)
2210          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2211      ErrorFound = true;
2212    }
2213
2214    Clause = ParseOpenMPClause(CKind, WrongDirective);
2215    break;
2216  case OMPC_private:
2217  case OMPC_firstprivate:
2218  case OMPC_lastprivate:
2219  case OMPC_shared:
2220  case OMPC_reduction:
2221  case OMPC_task_reduction:
2222  case OMPC_in_reduction:
2223  case OMPC_linear:
2224  case OMPC_aligned:
2225  case OMPC_copyin:
2226  case OMPC_copyprivate:
2227  case OMPC_flush:
2228  case OMPC_depend:
2229  case OMPC_map:
2230  case OMPC_to:
2231  case OMPC_from:
2232  case OMPC_use_device_ptr:
2233  case OMPC_is_device_ptr:
2234  case OMPC_allocate:
2235  case OMPC_nontemporal:
2236    Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
2237    break;
2238  case OMPC_device_type:
2239  case OMPC_unknown:
2240    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
2241        << getOpenMPDirectiveName(DKind);
2242    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
2243    break;
2244  case OMPC_threadprivate:
2245  case OMPC_uniform:
2246  case OMPC_match:
2247    if (!WrongDirective)
2248      Diag(Tok, diag::err_omp_unexpected_clause)
2249          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
2250    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
2251    break;
2252  }
2253  return ErrorFound ? nullptr : Clause;
2254}
2255
2256/// Parses simple expression in parens for single-expression clauses of OpenMP
2257/// constructs.
2258/// \param RLoc Returned location of right paren.
2259ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
2260                                         SourceLocation &RLoc,
2261                                         bool IsAddressOfOperand) {
2262  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2263  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
2264    return ExprError();
2265
2266  SourceLocation ELoc = Tok.getLocation();
2267  ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
2268                                     NotTypeCast));
2269  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
2270  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2271
2272  // Parse ')'.
2273  RLoc = Tok.getLocation();
2274  if (!T.consumeClose())
2275    RLoc = T.getCloseLocation();
2276
2277  return Val;
2278}
2279
2280/// Parsing of OpenMP clauses with single expressions like 'final',
2281/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
2282/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
2283///
2284///    final-clause:
2285///      'final' '(' expression ')'
2286///
2287///    num_threads-clause:
2288///      'num_threads' '(' expression ')'
2289///
2290///    safelen-clause:
2291///      'safelen' '(' expression ')'
2292///
2293///    simdlen-clause:
2294///      'simdlen' '(' expression ')'
2295///
2296///    collapse-clause:
2297///      'collapse' '(' expression ')'
2298///
2299///    priority-clause:
2300///      'priority' '(' expression ')'
2301///
2302///    grainsize-clause:
2303///      'grainsize' '(' expression ')'
2304///
2305///    num_tasks-clause:
2306///      'num_tasks' '(' expression ')'
2307///
2308///    hint-clause:
2309///      'hint' '(' expression ')'
2310///
2311///    allocator-clause:
2312///      'allocator' '(' expression ')'
2313///
2314OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
2315                                               bool ParseOnly) {
2316  SourceLocation Loc = ConsumeToken();
2317  SourceLocation LLoc = Tok.getLocation();
2318  SourceLocation RLoc;
2319
2320  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
2321
2322  if (Val.isInvalid())
2323    return nullptr;
2324
2325  if (ParseOnly)
2326    return nullptr;
2327  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
2328}
2329
2330/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
2331///
2332///    default-clause:
2333///         'default' '(' 'none' | 'shared' ')
2334///
2335///    proc_bind-clause:
2336///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
2337///
2338OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
2339                                           bool ParseOnly) {
2340  llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
2341  if (!Val || ParseOnly)
2342    return nullptr;
2343  return Actions.ActOnOpenMPSimpleClause(
2344      Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
2345      Val.getValue().Loc, Val.getValue().RLoc);
2346}
2347
2348/// Parsing of OpenMP clauses like 'ordered'.
2349///
2350///    ordered-clause:
2351///         'ordered'
2352///
2353///    nowait-clause:
2354///         'nowait'
2355///
2356///    untied-clause:
2357///         'untied'
2358///
2359///    mergeable-clause:
2360///         'mergeable'
2361///
2362///    read-clause:
2363///         'read'
2364///
2365///    threads-clause:
2366///         'threads'
2367///
2368///    simd-clause:
2369///         'simd'
2370///
2371///    nogroup-clause:
2372///         'nogroup'
2373///
2374OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
2375  SourceLocation Loc = Tok.getLocation();
2376  ConsumeAnyToken();
2377
2378  if (ParseOnly)
2379    return nullptr;
2380  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
2381}
2382
2383
2384/// Parsing of OpenMP clauses with single expressions and some additional
2385/// argument like 'schedule' or 'dist_schedule'.
2386///
2387///    schedule-clause:
2388///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
2389///      ')'
2390///
2391///    if-clause:
2392///      'if' '(' [ directive-name-modifier ':' ] expression ')'
2393///
2394///    defaultmap:
2395///      'defaultmap' '(' modifier ':' kind ')'
2396///
2397OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
2398                                                      bool ParseOnly) {
2399  SourceLocation Loc = ConsumeToken();
2400  SourceLocation DelimLoc;
2401  // Parse '('.
2402  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2403  if (T.expectAndConsume(diag::err_expected_lparen_after,
2404                         getOpenMPClauseName(Kind)))
2405    return nullptr;
2406
2407  ExprResult Val;
2408  SmallVector<unsigned, 4> Arg;
2409  SmallVector<SourceLocation, 4> KLoc;
2410  if (Kind == OMPC_schedule) {
2411    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
2412    Arg.resize(NumberOfElements);
2413    KLoc.resize(NumberOfElements);
2414    Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
2415    Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
2416    Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
2417    unsigned KindModifier = getOpenMPSimpleClauseType(
2418        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2419    if (KindModifier > OMPC_SCHEDULE_unknown) {
2420      // Parse 'modifier'
2421      Arg[Modifier1] = KindModifier;
2422      KLoc[Modifier1] = Tok.getLocation();
2423      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2424          Tok.isNot(tok::annot_pragma_openmp_end))
2425        ConsumeAnyToken();
2426      if (Tok.is(tok::comma)) {
2427        // Parse ',' 'modifier'
2428        ConsumeAnyToken();
2429        KindModifier = getOpenMPSimpleClauseType(
2430            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2431        Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
2432                             ? KindModifier
2433                             : (unsigned)OMPC_SCHEDULE_unknown;
2434        KLoc[Modifier2] = Tok.getLocation();
2435        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2436            Tok.isNot(tok::annot_pragma_openmp_end))
2437          ConsumeAnyToken();
2438      }
2439      // Parse ':'
2440      if (Tok.is(tok::colon))
2441        ConsumeAnyToken();
2442      else
2443        Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
2444      KindModifier = getOpenMPSimpleClauseType(
2445          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2446    }
2447    Arg[ScheduleKind] = KindModifier;
2448    KLoc[ScheduleKind] = Tok.getLocation();
2449    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2450        Tok.isNot(tok::annot_pragma_openmp_end))
2451      ConsumeAnyToken();
2452    if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
2453         Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
2454         Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
2455        Tok.is(tok::comma))
2456      DelimLoc = ConsumeAnyToken();
2457  } else if (Kind == OMPC_dist_schedule) {
2458    Arg.push_back(getOpenMPSimpleClauseType(
2459        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
2460    KLoc.push_back(Tok.getLocation());
2461    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2462        Tok.isNot(tok::annot_pragma_openmp_end))
2463      ConsumeAnyToken();
2464    if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
2465      DelimLoc = ConsumeAnyToken();
2466  } else if (Kind == OMPC_defaultmap) {
2467    // Get a defaultmap modifier
2468    unsigned Modifier = getOpenMPSimpleClauseType(
2469        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2470    // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
2471    // pointer
2472    if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
2473      Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
2474    Arg.push_back(Modifier);
2475    KLoc.push_back(Tok.getLocation());
2476    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2477        Tok.isNot(tok::annot_pragma_openmp_end))
2478      ConsumeAnyToken();
2479    // Parse ':'
2480    if (Tok.is(tok::colon))
2481      ConsumeAnyToken();
2482    else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
2483      Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
2484    // Get a defaultmap kind
2485    Arg.push_back(getOpenMPSimpleClauseType(
2486        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
2487    KLoc.push_back(Tok.getLocation());
2488    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2489        Tok.isNot(tok::annot_pragma_openmp_end))
2490      ConsumeAnyToken();
2491  } else {
2492    assert(Kind == OMPC_if);
2493    KLoc.push_back(Tok.getLocation());
2494    TentativeParsingAction TPA(*this);
2495    auto DK = parseOpenMPDirectiveKind(*this);
2496    Arg.push_back(DK);
2497    if (DK != OMPD_unknown) {
2498      ConsumeToken();
2499      if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
2500        TPA.Commit();
2501        DelimLoc = ConsumeToken();
2502      } else {
2503        TPA.Revert();
2504        Arg.back() = unsigned(OMPD_unknown);
2505      }
2506    } else {
2507      TPA.Revert();
2508    }
2509  }
2510
2511  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
2512                          (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
2513                          Kind == OMPC_if;
2514  if (NeedAnExpression) {
2515    SourceLocation ELoc = Tok.getLocation();
2516    ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
2517    Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
2518    Val =
2519        Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2520  }
2521
2522  // Parse ')'.
2523  SourceLocation RLoc = Tok.getLocation();
2524  if (!T.consumeClose())
2525    RLoc = T.getCloseLocation();
2526
2527  if (NeedAnExpression && Val.isInvalid())
2528    return nullptr;
2529
2530  if (ParseOnly)
2531    return nullptr;
2532  return Actions.ActOnOpenMPSingleExprWithArgClause(
2533      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
2534}
2535
2536static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
2537                             UnqualifiedId &ReductionId) {
2538  if (ReductionIdScopeSpec.isEmpty()) {
2539    auto OOK = OO_None;
2540    switch (P.getCurToken().getKind()) {
2541    case tok::plus:
2542      OOK = OO_Plus;
2543      break;
2544    case tok::minus:
2545      OOK = OO_Minus;
2546      break;
2547    case tok::star:
2548      OOK = OO_Star;
2549      break;
2550    case tok::amp:
2551      OOK = OO_Amp;
2552      break;
2553    case tok::pipe:
2554      OOK = OO_Pipe;
2555      break;
2556    case tok::caret:
2557      OOK = OO_Caret;
2558      break;
2559    case tok::ampamp:
2560      OOK = OO_AmpAmp;
2561      break;
2562    case tok::pipepipe:
2563      OOK = OO_PipePipe;
2564      break;
2565    default:
2566      break;
2567    }
2568    if (OOK != OO_None) {
2569      SourceLocation OpLoc = P.ConsumeToken();
2570      SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
2571      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
2572      return false;
2573    }
2574  }
2575  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
2576                              /*AllowDestructorName*/ false,
2577                              /*AllowConstructorName*/ false,
2578                              /*AllowDeductionGuide*/ false,
2579                              nullptr, nullptr, ReductionId);
2580}
2581
2582/// Checks if the token is a valid map-type-modifier.
2583static OpenMPMapModifierKind isMapModifier(Parser &P) {
2584  Token Tok = P.getCurToken();
2585  if (!Tok.is(tok::identifier))
2586    return OMPC_MAP_MODIFIER_unknown;
2587
2588  Preprocessor &PP = P.getPreprocessor();
2589  OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
2590      getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2591  return TypeModifier;
2592}
2593
2594/// Parse the mapper modifier in map, to, and from clauses.
2595bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
2596  // Parse '('.
2597  BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
2598  if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
2599    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2600              StopBeforeMatch);
2601    return true;
2602  }
2603  // Parse mapper-identifier
2604  if (getLangOpts().CPlusPlus)
2605    ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2606                                   /*ObjectType=*/nullptr,
2607                                   /*EnteringContext=*/false);
2608  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
2609    Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
2610    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2611              StopBeforeMatch);
2612    return true;
2613  }
2614  auto &DeclNames = Actions.getASTContext().DeclarationNames;
2615  Data.ReductionOrMapperId = DeclarationNameInfo(
2616      DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
2617  ConsumeToken();
2618  // Parse ')'.
2619  return T.consumeClose();
2620}
2621
2622/// Parse map-type-modifiers in map clause.
2623/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2624/// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
2625bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
2626  while (getCurToken().isNot(tok::colon)) {
2627    OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
2628    if (TypeModifier == OMPC_MAP_MODIFIER_always ||
2629        TypeModifier == OMPC_MAP_MODIFIER_close) {
2630      Data.MapTypeModifiers.push_back(TypeModifier);
2631      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2632      ConsumeToken();
2633    } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
2634      Data.MapTypeModifiers.push_back(TypeModifier);
2635      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2636      ConsumeToken();
2637      if (parseMapperModifier(Data))
2638        return true;
2639    } else {
2640      // For the case of unknown map-type-modifier or a map-type.
2641      // Map-type is followed by a colon; the function returns when it
2642      // encounters a token followed by a colon.
2643      if (Tok.is(tok::comma)) {
2644        Diag(Tok, diag::err_omp_map_type_modifier_missing);
2645        ConsumeToken();
2646        continue;
2647      }
2648      // Potential map-type token as it is followed by a colon.
2649      if (PP.LookAhead(0).is(tok::colon))
2650        return false;
2651      Diag(Tok, diag::err_omp_unknown_map_type_modifier);
2652      ConsumeToken();
2653    }
2654    if (getCurToken().is(tok::comma))
2655      ConsumeToken();
2656  }
2657  return false;
2658}
2659
2660/// Checks if the token is a valid map-type.
2661static OpenMPMapClauseKind isMapType(Parser &P) {
2662  Token Tok = P.getCurToken();
2663  // The map-type token can be either an identifier or the C++ delete keyword.
2664  if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
2665    return OMPC_MAP_unknown;
2666  Preprocessor &PP = P.getPreprocessor();
2667  OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
2668      getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2669  return MapType;
2670}
2671
2672/// Parse map-type in map clause.
2673/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2674/// where, map-type ::= to | from | tofrom | alloc | release | delete
2675static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
2676  Token Tok = P.getCurToken();
2677  if (Tok.is(tok::colon)) {
2678    P.Diag(Tok, diag::err_omp_map_type_missing);
2679    return;
2680  }
2681  Data.ExtraModifier = isMapType(P);
2682  if (Data.ExtraModifier == OMPC_MAP_unknown)
2683    P.Diag(Tok, diag::err_omp_unknown_map_type);
2684  P.ConsumeToken();
2685}
2686
2687/// Parses clauses with list.
2688bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
2689                                OpenMPClauseKind Kind,
2690                                SmallVectorImpl<Expr *> &Vars,
2691                                OpenMPVarListDataTy &Data) {
2692  UnqualifiedId UnqualifiedReductionId;
2693  bool InvalidReductionId = false;
2694  bool IsInvalidMapperModifier = false;
2695
2696  // Parse '('.
2697  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2698  if (T.expectAndConsume(diag::err_expected_lparen_after,
2699                         getOpenMPClauseName(Kind)))
2700    return true;
2701
2702  bool NeedRParenForLinear = false;
2703  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
2704                                  tok::annot_pragma_openmp_end);
2705  // Handle reduction-identifier for reduction clause.
2706  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
2707      Kind == OMPC_in_reduction) {
2708    ColonProtectionRAIIObject ColonRAII(*this);
2709    if (getLangOpts().CPlusPlus)
2710      ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2711                                     /*ObjectType=*/nullptr,
2712                                     /*EnteringContext=*/false);
2713    InvalidReductionId = ParseReductionId(
2714        *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
2715    if (InvalidReductionId) {
2716      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2717                StopBeforeMatch);
2718    }
2719    if (Tok.is(tok::colon))
2720      Data.ColonLoc = ConsumeToken();
2721    else
2722      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
2723    if (!InvalidReductionId)
2724      Data.ReductionOrMapperId =
2725          Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
2726  } else if (Kind == OMPC_depend) {
2727    // Handle dependency type for depend clause.
2728    ColonProtectionRAIIObject ColonRAII(*this);
2729    Data.ExtraModifier = getOpenMPSimpleClauseType(
2730        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "");
2731    Data.DepLinMapLastLoc = Tok.getLocation();
2732    if (Data.ExtraModifier == OMPC_DEPEND_unknown) {
2733      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2734                StopBeforeMatch);
2735    } else {
2736      ConsumeToken();
2737      // Special processing for depend(source) clause.
2738      if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {
2739        // Parse ')'.
2740        T.consumeClose();
2741        return false;
2742      }
2743    }
2744    if (Tok.is(tok::colon)) {
2745      Data.ColonLoc = ConsumeToken();
2746    } else {
2747      Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
2748                                      : diag::warn_pragma_expected_colon)
2749          << "dependency type";
2750    }
2751  } else if (Kind == OMPC_linear) {
2752    // Try to parse modifier if any.
2753    Data.ExtraModifier = OMPC_LINEAR_val;
2754    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
2755      Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
2756      Data.DepLinMapLastLoc = ConsumeToken();
2757      LinearT.consumeOpen();
2758      NeedRParenForLinear = true;
2759    }
2760  } else if (Kind == OMPC_lastprivate) {
2761    // Try to parse modifier if any.
2762    Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
2763    // Conditional modifier allowed only in OpenMP 5.0 and not supported in
2764    // distribute and taskloop based directives.
2765    if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
2766         !isOpenMPTaskLoopDirective(DKind)) &&
2767        Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
2768      Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
2769      Data.DepLinMapLastLoc = Tok.getLocation();
2770      if (Data.ExtraModifier == OMPC_LASTPRIVATE_unknown) {
2771        SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2772                  StopBeforeMatch);
2773      } else {
2774        ConsumeToken();
2775      }
2776      assert(Tok.is(tok::colon) && "Expected colon.");
2777      Data.ColonLoc = ConsumeToken();
2778    }
2779  } else if (Kind == OMPC_map) {
2780    // Handle map type for map clause.
2781    ColonProtectionRAIIObject ColonRAII(*this);
2782
2783    // The first identifier may be a list item, a map-type or a
2784    // map-type-modifier. The map-type can also be delete which has the same
2785    // spelling of the C++ delete keyword.
2786    Data.ExtraModifier = OMPC_MAP_unknown;
2787    Data.DepLinMapLastLoc = Tok.getLocation();
2788
2789    // Check for presence of a colon in the map clause.
2790    TentativeParsingAction TPA(*this);
2791    bool ColonPresent = false;
2792    if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2793        StopBeforeMatch)) {
2794      if (Tok.is(tok::colon))
2795        ColonPresent = true;
2796    }
2797    TPA.Revert();
2798    // Only parse map-type-modifier[s] and map-type if a colon is present in
2799    // the map clause.
2800    if (ColonPresent) {
2801      IsInvalidMapperModifier = parseMapTypeModifiers(Data);
2802      if (!IsInvalidMapperModifier)
2803        parseMapType(*this, Data);
2804      else
2805        SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
2806    }
2807    if (Data.ExtraModifier == OMPC_MAP_unknown) {
2808      Data.ExtraModifier = OMPC_MAP_tofrom;
2809      Data.IsMapTypeImplicit = true;
2810    }
2811
2812    if (Tok.is(tok::colon))
2813      Data.ColonLoc = ConsumeToken();
2814  } else if (Kind == OMPC_to || Kind == OMPC_from) {
2815    if (Tok.is(tok::identifier)) {
2816      bool IsMapperModifier = false;
2817      if (Kind == OMPC_to) {
2818        auto Modifier = static_cast<OpenMPToModifierKind>(
2819            getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2820        if (Modifier == OMPC_TO_MODIFIER_mapper)
2821          IsMapperModifier = true;
2822      } else {
2823        auto Modifier = static_cast<OpenMPFromModifierKind>(
2824            getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2825        if (Modifier == OMPC_FROM_MODIFIER_mapper)
2826          IsMapperModifier = true;
2827      }
2828      if (IsMapperModifier) {
2829        // Parse the mapper modifier.
2830        ConsumeToken();
2831        IsInvalidMapperModifier = parseMapperModifier(Data);
2832        if (Tok.isNot(tok::colon)) {
2833          if (!IsInvalidMapperModifier)
2834            Diag(Tok, diag::warn_pragma_expected_colon) << ")";
2835          SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2836                    StopBeforeMatch);
2837        }
2838        // Consume ':'.
2839        if (Tok.is(tok::colon))
2840          ConsumeToken();
2841      }
2842    }
2843  } else if (Kind == OMPC_allocate) {
2844    // Handle optional allocator expression followed by colon delimiter.
2845    ColonProtectionRAIIObject ColonRAII(*this);
2846    TentativeParsingAction TPA(*this);
2847    ExprResult Tail =
2848        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2849    Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
2850                                       /*DiscardedValue=*/false);
2851    if (Tail.isUsable()) {
2852      if (Tok.is(tok::colon)) {
2853        Data.TailExpr = Tail.get();
2854        Data.ColonLoc = ConsumeToken();
2855        TPA.Commit();
2856      } else {
2857        // colon not found, no allocator specified, parse only list of
2858        // variables.
2859        TPA.Revert();
2860      }
2861    } else {
2862      // Parsing was unsuccessfull, revert and skip to the end of clause or
2863      // directive.
2864      TPA.Revert();
2865      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2866                StopBeforeMatch);
2867    }
2868  }
2869
2870  bool IsComma =
2871      (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
2872       Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
2873      (Kind == OMPC_reduction && !InvalidReductionId) ||
2874      (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
2875      (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
2876  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
2877  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
2878                     Tok.isNot(tok::annot_pragma_openmp_end))) {
2879    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
2880    // Parse variable
2881    ExprResult VarExpr =
2882        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2883    if (VarExpr.isUsable()) {
2884      Vars.push_back(VarExpr.get());
2885    } else {
2886      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2887                StopBeforeMatch);
2888    }
2889    // Skip ',' if any
2890    IsComma = Tok.is(tok::comma);
2891    if (IsComma)
2892      ConsumeToken();
2893    else if (Tok.isNot(tok::r_paren) &&
2894             Tok.isNot(tok::annot_pragma_openmp_end) &&
2895             (!MayHaveTail || Tok.isNot(tok::colon)))
2896      Diag(Tok, diag::err_omp_expected_punc)
2897          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
2898                                   : getOpenMPClauseName(Kind))
2899          << (Kind == OMPC_flush);
2900  }
2901
2902  // Parse ')' for linear clause with modifier.
2903  if (NeedRParenForLinear)
2904    LinearT.consumeClose();
2905
2906  // Parse ':' linear-step (or ':' alignment).
2907  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
2908  if (MustHaveTail) {
2909    Data.ColonLoc = Tok.getLocation();
2910    SourceLocation ELoc = ConsumeToken();
2911    ExprResult Tail = ParseAssignmentExpression();
2912    Tail =
2913        Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
2914    if (Tail.isUsable())
2915      Data.TailExpr = Tail.get();
2916    else
2917      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2918                StopBeforeMatch);
2919  }
2920
2921  // Parse ')'.
2922  Data.RLoc = Tok.getLocation();
2923  if (!T.consumeClose())
2924    Data.RLoc = T.getCloseLocation();
2925  return (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown &&
2926          Vars.empty()) ||
2927         (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
2928         (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
2929         IsInvalidMapperModifier;
2930}
2931
2932/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
2933/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
2934/// 'in_reduction'.
2935///
2936///    private-clause:
2937///       'private' '(' list ')'
2938///    firstprivate-clause:
2939///       'firstprivate' '(' list ')'
2940///    lastprivate-clause:
2941///       'lastprivate' '(' list ')'
2942///    shared-clause:
2943///       'shared' '(' list ')'
2944///    linear-clause:
2945///       'linear' '(' linear-list [ ':' linear-step ] ')'
2946///    aligned-clause:
2947///       'aligned' '(' list [ ':' alignment ] ')'
2948///    reduction-clause:
2949///       'reduction' '(' reduction-identifier ':' list ')'
2950///    task_reduction-clause:
2951///       'task_reduction' '(' reduction-identifier ':' list ')'
2952///    in_reduction-clause:
2953///       'in_reduction' '(' reduction-identifier ':' list ')'
2954///    copyprivate-clause:
2955///       'copyprivate' '(' list ')'
2956///    flush-clause:
2957///       'flush' '(' list ')'
2958///    depend-clause:
2959///       'depend' '(' in | out | inout : list | source ')'
2960///    map-clause:
2961///       'map' '(' [ [ always [,] ] [ close [,] ]
2962///          [ mapper '(' mapper-identifier ')' [,] ]
2963///          to | from | tofrom | alloc | release | delete ':' ] list ')';
2964///    to-clause:
2965///       'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2966///    from-clause:
2967///       'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2968///    use_device_ptr-clause:
2969///       'use_device_ptr' '(' list ')'
2970///    is_device_ptr-clause:
2971///       'is_device_ptr' '(' list ')'
2972///    allocate-clause:
2973///       'allocate' '(' [ allocator ':' ] list ')'
2974///
2975/// For 'linear' clause linear-list may have the following forms:
2976///  list
2977///  modifier(list)
2978/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
2979OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
2980                                            OpenMPClauseKind Kind,
2981                                            bool ParseOnly) {
2982  SourceLocation Loc = Tok.getLocation();
2983  SourceLocation LOpen = ConsumeToken();
2984  SmallVector<Expr *, 4> Vars;
2985  OpenMPVarListDataTy Data;
2986
2987  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
2988    return nullptr;
2989
2990  if (ParseOnly)
2991    return nullptr;
2992  OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
2993  return Actions.ActOnOpenMPVarListClause(
2994      Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
2995      Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
2996      Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
2997      Data.IsMapTypeImplicit, Data.DepLinMapLastLoc);
2998}
2999
3000