clang  10.0.0git
ParseOpenMP.cpp
Go to the documentation of this file.
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"
17 #include "clang/Parse/Parser.h"
19 #include "clang/Sema/Scope.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 #include "llvm/ADT/UniqueVector.h"
22 
23 using namespace clang;
24 using namespace llvm::omp;
25 
26 //===----------------------------------------------------------------------===//
27 // OpenMP declarative directives.
28 //===----------------------------------------------------------------------===//
29 
30 namespace {
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.
54 struct 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 
65 class DeclDirectiveListParserHelper final {
66  SmallVector<Expr *, 4> Identifiers;
67  Parser *P;
69 
70 public:
71  DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
72  : P(P), Kind(Kind) {}
73  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
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.
85 static 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 
105 static 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)
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)
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 
192  Token Tok = P.getCurToken();
193  Sema &Actions = P.getActions();
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,
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 ///
254 Parser::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 
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 
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 |
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 |
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 
418 void 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 
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 ///
505 Parser::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 |
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.
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 
609 TypeResult 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.
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 
631 namespace {
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.
637 class 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 
648 public:
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(
670  HasFunScope);
671  if (HasFunScope)
672  Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
673  }
674  ~FNContextRAII() {
675  if (HasFunScope) {
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> ] ')' }
696  Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
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) {
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 &&
753  "Unexpected linear modifier.");
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'.
775 Parser::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;
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> ')' ':'.
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 /// ')'
836 static void
838  llvm::StringMap<SourceLocation> &UsedCtx,
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> } ')'
912 static void
914  llvm::StringMap<SourceLocation> &UsedCtx,
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);
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> '}' ]
999 bool Parser::parseOpenMPContextSelectors(
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)
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;
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'.
1072 void 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.
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  }
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)
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,
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.
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' )'
1167 namespace {
1168  struct SimpleClauseData {
1169  unsigned Type;
1170  SourceLocation Loc;
1171  SourceLocation LOpen;
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 
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));
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 
1206 Parser::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 =
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;
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 
1292 void 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 ///
1337 Parser::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)) {
1404  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
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();
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) {
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 
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) {
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 ///
1706 StmtResult
1707 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1708  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1709  ParsingOpenMPDirectiveRAII DirScope(*this);
1710  ParenBraceBracketBalancer BalancerRAIIObj(*this);
1713  FirstClauses(OMPC_unknown + 1);
1714  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
1716  SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
1718  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
1719  // Name of critical directive.
1720  DeclarationNameInfo DirName;
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)) {
1763  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
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 //
2014 bool Parser::ParseOpenMPSimpleVarList(
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 ///
2089 OMPClause *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.
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 ///
2314 OMPClause *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 ///
2338 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
2339  bool ParseOnly) {
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 ///
2374 OMPClause *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 ///
2397 OMPClause *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,
2405  return nullptr;
2406 
2407  ExprResult Val;
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
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)
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 
2536 static 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.
2584  Token Tok = P.getCurToken();
2585  if (!Tok.is(tok::identifier))
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.
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;
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)
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.
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
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.
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);
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.
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();
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.
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++).
2979 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
2981  bool ParseOnly) {
2982  SourceLocation Loc = Tok.getLocation();
2983  SourceLocation LOpen = ConsumeToken();
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,
2997  Data.IsMapTypeImplicit, Data.DepLinMapLastLoc);
2998 }
2999 
OpenMPFromModifierKind
OpenMP modifier kind for &#39;from&#39; clause.
Definition: OpenMPKinds.h:143
Defines the clang::ASTContext interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
PtrTy get() const
Definition: Ownership.h:80
ParseScope - Introduces a new scope for parsing.
Definition: Parser.h:1024
A (possibly-)qualified type.
Definition: Type.h:654
bool operator==(CanQual< T > x, CanQual< U > y)
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
Definition: Token.h:97
DeclarationNameInfo ReductionOrMapperId
Definition: Parser.h:3031
bool isEmpty() const
No scope specifier.
Definition: DeclSpec.h:189
iterator end()
Definition: DeclGroup.h:105
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
SmallVector< OpenMPMapModifierKind, OMPMapClause::NumberOfModifiers > MapTypeModifiers
Definition: Parser.h:3035
StringRef P
The base class of the type hierarchy.
Definition: Type.h:1450
SourceLocation getCloseLocation() const
This indicates that the scope corresponds to a function, which means that labels are set here...
Definition: Scope.h:47
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:113
void ActOnExitFunctionContext()
Definition: SemaDecl.cpp:1398
Wrapper for void* pointer.
Definition: Ownership.h:50
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:57
bool isEmpty() const
Evaluates true when this declaration name is empty.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
RAII object that enters a new expression evaluation context.
Definition: Sema.h:12029
Represents a variable declaration or definition.
Definition: Decl.h:820
ActionResult< Stmt * > StmtResult
Definition: Ownership.h:264
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1792
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:60
RAII object used to temporarily allow the C++ &#39;this&#39; expression to be used, with the given qualifiers...
Definition: Sema.h:5616
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Definition: Token.h:120
static Optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed...
tok::TokenKind getKind() const
Definition: Token.h:92
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
Definition: Parser.h:1118
The collection of all-type qualifiers we support.
Definition: Type.h:143
OpenMPMapModifierKind
OpenMP modifier kind for &#39;map&#39; clause.
Definition: OpenMPKinds.h:126
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:58
Represents a struct/union/class.
Definition: Decl.h:3748
bool TryConsumeToken(tok::TokenKind Expected)
Definition: Parser.h:460
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
Definition: OpenMPKinds.cpp:82
One of these records is kept for each identifier that is lexed.
OpenMPContextSelectorKind
OpenMP context selectors.
Definition: OpenMPKinds.h:30
static void parseDeviceSelector(Parser &P, SourceLocation Loc, llvm::StringMap< SourceLocation > &UsedCtx, SmallVectorImpl< Sema::OMPCtxSelectorData > &Data)
Parse context selector for &#39;device&#39; selector set: &#39;kind&#39; &#39;(&#39; <kind> { &#39;,&#39; <kind> } &#39;)&#39;...
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
Defines some OpenMP-specific enums and functions.
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition: Ownership.h:244
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:960
PtrTy get() const
Definition: Ownership.h:170
OpenMPContextSelectorSetKind
OpenMP context selector sets.
Definition: OpenMPKinds.h:23
bool isNot(T Kind) const
Definition: FormatToken.h:330
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the &#39;spelling&#39; of the token at the given location; does not go up to the spelling location or ...
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion)
const FormatToken & Tok
StmtResult StmtError()
Definition: Ownership.h:280
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str)
iterator begin()
Definition: DeclGroup.h:99
static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, SmallVectorImpl< Expr *> &Uniforms, SmallVectorImpl< Expr *> &Aligneds, SmallVectorImpl< Expr *> &Alignments, SmallVectorImpl< Expr *> &Linears, SmallVectorImpl< unsigned > &LinModifiers, SmallVectorImpl< Expr *> &Steps)
Parses clauses for &#39;declare simd&#39; directive.
OpenMPContextSelectorSetKind getOpenMPContextSelectorSet(llvm::StringRef Str)
Definition: OpenMPKinds.cpp:24
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the &#39;#pragma omp threadprivate&#39;.
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:63
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type...
Definition: Parser.h:480
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:62
IdentifierInfo * getIdentifier() const
Definition: DeclSpec.h:2172
static void parseImplementationSelector(Parser &P, SourceLocation Loc, llvm::StringMap< SourceLocation > &UsedCtx, SmallVectorImpl< Sema::OMPCtxSelectorData > &Data)
Parse context selector for &#39;implementation&#39; selector set: &#39;vendor&#39; &#39;(&#39; [ &#39;score&#39; &#39;(&#39; <score _expr>=""...
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:336
A RAII object to enter scope of a compound statement.
Definition: Sema.h:4114
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:583
This is the scope of OpenMP executable directive.
Definition: Scope.h:107
Sema & getActions() const
Definition: Parser.h:410
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, ParsedType ObjectType, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
#define V(N, I)
Definition: ASTContext.h:2941
const Token & getCurToken() const
Definition: Parser.h:413
OpenMPDirectiveKindEx
Definition: ParseOpenMP.cpp:31
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:126
OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:65
DeclContext * getDeclContext()
Definition: DeclBase.h:438
This is a compound statement scope.
Definition: Scope.h:130
static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7)...
Preprocessor & getPreprocessor() const
Definition: Parser.h:409
DeclaratorContext
Definition: DeclSpec.h:1749
SmallVector< SourceLocation, OMPMapClause::NumberOfModifiers > MapTypeModifiersLoc
Definition: Parser.h:3037
bool isInvalid() const
Definition: Ownership.h:166
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
SourceLocation getOpenLocation() const
bool isUsable() const
Definition: Ownership.h:167
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:719
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
A class for parsing a DeclSpec.
bool isTemplateDecl() const
returns true if this declaration is a template
Definition: DeclBase.cpp:226
Kind
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Definition: Ownership.h:153
ASTContext & getASTContext() const
Definition: Sema.h:1331
Encodes a location in the source.
bool is(tok::TokenKind Kind) const
Definition: FormatToken.h:314
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr *> &Vars, OpenMPVarListDataTy &Data)
Parses clauses with list.
static unsigned getOpenMPDirectiveKindEx(StringRef S)
Definition: ParseOpenMP.cpp:85
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:179
OpenMPLinearClauseKind Modifier
Modifier of &#39;linear&#39; clause.
Definition: OpenMPClause.h:101
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:51
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Scope * getCurScope() const
Definition: Parser.h:414
StringRef getName() const
Return the actual identifier string.
SourceRange getSourceRange() const LLVM_READONLY
Get the source range that spans this declarator.
Definition: DeclSpec.h:1930
bool isNot(tok::TokenKind K) const
Definition: Token.h:98
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
Definition: Parser.cpp:2489
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
This is the scope of some OpenMP simd directive.
Definition: Scope.h:115
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition: DeclBase.h:1018
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This is a scope that corresponds to the template parameters of a C++ template.
Definition: Scope.h:77
The name of a declaration.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
Definition: Token.h:99
Data used for parsing list of variables in OpenMP clauses.
Definition: Parser.h:3026
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P)
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
static const TST TST_unspecified
Definition: DeclSpec.h:272
OpenMPToModifierKind
OpenMP modifier kind for &#39;to&#39; clause.
Definition: OpenMPKinds.h:135
CXXScopeSpec ReductionOrMapperIdScopeSpec
Definition: Parser.h:3030
Not an overloaded operator.
Definition: OperatorKinds.h:22
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
QualType getCanonicalTypeInternal() const
Definition: Type.h:2429
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Definition: Parser.cpp:72
This file defines OpenMP AST classes for executable directives and clauses.
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
Definition: DeclSpec.cpp:1377
int ExtraModifier
Additional modifier for linear, map, depend or lastprivate clause.
Definition: Parser.h:3032
This is a scope that can contain a declaration.
Definition: Scope.h:59
Captures information about "declaration specifiers".
Definition: DeclSpec.h:228
SourceLocation ConsumeToken()
ConsumeToken - Consume the current &#39;peek token&#39; and lex the next one.
Definition: Parser.h:452
OpenMPMapClauseKind
OpenMP mapping kind for &#39;map&#39; clause.
Definition: OpenMPKinds.h:118
bool operator!=(CanQual< T > x, CanQual< U > y)
static DeclarationName parseOpenMPReductionId(Parser &P)
This represents &#39;#pragma omp declare mapper ...&#39; directive.
Definition: DeclOpenMP.h:217
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
This is the scope of some OpenMP loop directive.
Definition: Scope.h:110
ExprResult ExprError()
Definition: Ownership.h:279
bool parseMapTypeModifiers(OpenMPVarListDataTy &Data)
Parses map-type-modifiers in map clause.
OpenMPContextSelectorKind getOpenMPContextSelector(llvm::StringRef Str)
Definition: OpenMPKinds.cpp:45
bool parseMapperModifier(OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
This structure contains most locations needed for by an OMPVarListClause.
Definition: OpenMPClause.h:172
static ExprResult parseContextScore(Parser &P)
Parse optional &#39;score&#39; &#39;(&#39; <expr> &#39;)&#39; &#39;:&#39;.
QualType getType() const
Definition: Decl.h:630
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
Definition: Decl.h:223
Directive - Abstract class representing a parsed verify directive.
SourceLocation getBegin() const
VerifyDiagnosticConsumer::Directive Directive
SourceLocation getLocation() const
Definition: DeclBase.h:429
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:128
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition: Decl.cpp:1790
Stop skipping at specified token, but don&#39;t skip the token itself.
Definition: Parser.h:1100
SourceLocation getEndLoc() const
Definition: Token.h:153