clang  10.0.0svn
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"
16 #include "clang/Parse/Parser.h"
18 #include "clang/Sema/Scope.h"
19 #include "llvm/ADT/PointerIntPair.h"
20 
21 using namespace clang;
22 
23 //===----------------------------------------------------------------------===//
24 // OpenMP declarative directives.
25 //===----------------------------------------------------------------------===//
26 
27 namespace {
29  OMPD_cancellation = OMPD_unknown + 1,
30  OMPD_data,
31  OMPD_declare,
32  OMPD_end,
33  OMPD_end_declare,
34  OMPD_enter,
35  OMPD_exit,
36  OMPD_point,
37  OMPD_reduction,
38  OMPD_target_enter,
39  OMPD_target_exit,
40  OMPD_update,
41  OMPD_distribute_parallel,
42  OMPD_teams_distribute_parallel,
43  OMPD_target_teams_distribute_parallel,
44  OMPD_mapper,
45 };
46 
47 class DeclDirectiveListParserHelper final {
48  SmallVector<Expr *, 4> Identifiers;
49  Parser *P;
51 
52 public:
53  DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
54  : P(P), Kind(Kind) {}
55  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
57  P->getCurScope(), SS, NameInfo, Kind);
58  if (Res.isUsable())
59  Identifiers.push_back(Res.get());
60  }
61  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
62 };
63 } // namespace
64 
65 // Map token string to extended OMP token kind that are
66 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
67 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
68  auto DKind = getOpenMPDirectiveKind(S);
69  if (DKind != OMPD_unknown)
70  return DKind;
71 
72  return llvm::StringSwitch<unsigned>(S)
73  .Case("cancellation", OMPD_cancellation)
74  .Case("data", OMPD_data)
75  .Case("declare", OMPD_declare)
76  .Case("end", OMPD_end)
77  .Case("enter", OMPD_enter)
78  .Case("exit", OMPD_exit)
79  .Case("point", OMPD_point)
80  .Case("reduction", OMPD_reduction)
81  .Case("update", OMPD_update)
82  .Case("mapper", OMPD_mapper)
83  .Default(OMPD_unknown);
84 }
85 
87  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
88  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
89  // TODO: add other combined directives in topological order.
90  static const unsigned F[][3] = {
91  {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
92  {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
93  {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
94  {OMPD_declare, OMPD_simd, OMPD_declare_simd},
95  {OMPD_declare, OMPD_target, OMPD_declare_target},
96  {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
97  {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
98  {OMPD_distribute_parallel_for, OMPD_simd,
99  OMPD_distribute_parallel_for_simd},
100  {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
101  {OMPD_end, OMPD_declare, OMPD_end_declare},
102  {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
103  {OMPD_target, OMPD_data, OMPD_target_data},
104  {OMPD_target, OMPD_enter, OMPD_target_enter},
105  {OMPD_target, OMPD_exit, OMPD_target_exit},
106  {OMPD_target, OMPD_update, OMPD_target_update},
107  {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
108  {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
109  {OMPD_for, OMPD_simd, OMPD_for_simd},
110  {OMPD_parallel, OMPD_for, OMPD_parallel_for},
111  {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
112  {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
113  {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
114  {OMPD_target, OMPD_parallel, OMPD_target_parallel},
115  {OMPD_target, OMPD_simd, OMPD_target_simd},
116  {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
117  {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
118  {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
119  {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
120  {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
121  {OMPD_teams_distribute_parallel, OMPD_for,
122  OMPD_teams_distribute_parallel_for},
123  {OMPD_teams_distribute_parallel_for, OMPD_simd,
124  OMPD_teams_distribute_parallel_for_simd},
125  {OMPD_target, OMPD_teams, OMPD_target_teams},
126  {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
127  {OMPD_target_teams_distribute, OMPD_parallel,
128  OMPD_target_teams_distribute_parallel},
129  {OMPD_target_teams_distribute, OMPD_simd,
130  OMPD_target_teams_distribute_simd},
131  {OMPD_target_teams_distribute_parallel, OMPD_for,
132  OMPD_target_teams_distribute_parallel_for},
133  {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
134  OMPD_target_teams_distribute_parallel_for_simd}};
135  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
136  Token Tok = P.getCurToken();
137  unsigned DKind =
138  Tok.isAnnotation()
139  ? static_cast<unsigned>(OMPD_unknown)
141  if (DKind == OMPD_unknown)
142  return OMPD_unknown;
143 
144  for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
145  if (DKind != F[I][0])
146  continue;
147 
148  Tok = P.getPreprocessor().LookAhead(0);
149  unsigned SDKind =
150  Tok.isAnnotation()
151  ? static_cast<unsigned>(OMPD_unknown)
153  if (SDKind == OMPD_unknown)
154  continue;
155 
156  if (SDKind == F[I][1]) {
157  P.ConsumeToken();
158  DKind = F[I][2];
159  }
160  }
161  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
162  : OMPD_unknown;
163 }
164 
166  Token Tok = P.getCurToken();
167  Sema &Actions = P.getActions();
169  // Allow to use 'operator' keyword for C++ operators
170  bool WithOperator = false;
171  if (Tok.is(tok::kw_operator)) {
172  P.ConsumeToken();
173  Tok = P.getCurToken();
174  WithOperator = true;
175  }
176  switch (Tok.getKind()) {
177  case tok::plus: // '+'
178  OOK = OO_Plus;
179  break;
180  case tok::minus: // '-'
181  OOK = OO_Minus;
182  break;
183  case tok::star: // '*'
184  OOK = OO_Star;
185  break;
186  case tok::amp: // '&'
187  OOK = OO_Amp;
188  break;
189  case tok::pipe: // '|'
190  OOK = OO_Pipe;
191  break;
192  case tok::caret: // '^'
193  OOK = OO_Caret;
194  break;
195  case tok::ampamp: // '&&'
196  OOK = OO_AmpAmp;
197  break;
198  case tok::pipepipe: // '||'
199  OOK = OO_PipePipe;
200  break;
201  case tok::identifier: // identifier
202  if (!WithOperator)
203  break;
204  LLVM_FALLTHROUGH;
205  default:
206  P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
207  P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
209  return DeclarationName();
210  }
211  P.ConsumeToken();
212  auto &DeclNames = Actions.getASTContext().DeclarationNames;
213  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
214  : DeclNames.getCXXOperatorName(OOK);
215 }
216 
217 /// Parse 'omp declare reduction' construct.
218 ///
219 /// declare-reduction-directive:
220 /// annot_pragma_openmp 'declare' 'reduction'
221 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
222 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
223 /// annot_pragma_openmp_end
224 /// <reduction_id> is either a base language identifier or one of the following
225 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
226 ///
228 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
229  // Parse '('.
230  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
231  if (T.expectAndConsume(diag::err_expected_lparen_after,
232  getOpenMPDirectiveName(OMPD_declare_reduction))) {
233  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
234  return DeclGroupPtrTy();
235  }
236 
238  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
239  return DeclGroupPtrTy();
240 
241  // Consume ':'.
242  bool IsCorrect = !ExpectAndConsume(tok::colon);
243 
244  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
245  return DeclGroupPtrTy();
246 
247  IsCorrect = IsCorrect && !Name.isEmpty();
248 
249  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
250  Diag(Tok.getLocation(), diag::err_expected_type);
251  IsCorrect = false;
252  }
253 
254  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
255  return DeclGroupPtrTy();
256 
258  // Parse list of types until ':' token.
259  do {
260  ColonProtectionRAIIObject ColonRAII(*this);
261  SourceRange Range;
262  TypeResult TR =
263  ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
264  if (TR.isUsable()) {
265  QualType ReductionType =
266  Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
267  if (!ReductionType.isNull()) {
268  ReductionTypes.push_back(
269  std::make_pair(ReductionType, Range.getBegin()));
270  }
271  } else {
272  SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
273  StopBeforeMatch);
274  }
275 
276  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
277  break;
278 
279  // Consume ','.
280  if (ExpectAndConsume(tok::comma)) {
281  IsCorrect = false;
282  if (Tok.is(tok::annot_pragma_openmp_end)) {
283  Diag(Tok.getLocation(), diag::err_expected_type);
284  return DeclGroupPtrTy();
285  }
286  }
287  } while (Tok.isNot(tok::annot_pragma_openmp_end));
288 
289  if (ReductionTypes.empty()) {
290  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
291  return DeclGroupPtrTy();
292  }
293 
294  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
295  return DeclGroupPtrTy();
296 
297  // Consume ':'.
298  if (ExpectAndConsume(tok::colon))
299  IsCorrect = false;
300 
301  if (Tok.is(tok::annot_pragma_openmp_end)) {
302  Diag(Tok.getLocation(), diag::err_expected_expression);
303  return DeclGroupPtrTy();
304  }
305 
306  DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
307  getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
308 
309  // Parse <combiner> expression and then parse initializer if any for each
310  // correct type.
311  unsigned I = 0, E = ReductionTypes.size();
312  for (Decl *D : DRD.get()) {
313  TentativeParsingAction TPA(*this);
314  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
317  // Parse <combiner> expression.
318  Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
319  ExprResult CombinerResult =
320  Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
321  D->getLocation(), /*DiscardedValue*/ false);
322  Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
323 
324  if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
325  Tok.isNot(tok::annot_pragma_openmp_end)) {
326  TPA.Commit();
327  IsCorrect = false;
328  break;
329  }
330  IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
331  ExprResult InitializerResult;
332  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
333  // Parse <initializer> expression.
334  if (Tok.is(tok::identifier) &&
335  Tok.getIdentifierInfo()->isStr("initializer")) {
336  ConsumeToken();
337  } else {
338  Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
339  TPA.Commit();
340  IsCorrect = false;
341  break;
342  }
343  // Parse '('.
344  BalancedDelimiterTracker T(*this, tok::l_paren,
345  tok::annot_pragma_openmp_end);
346  IsCorrect =
347  !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
348  IsCorrect;
349  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
350  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
353  // Parse expression.
354  VarDecl *OmpPrivParm =
355  Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
356  D);
357  // Check if initializer is omp_priv <init_expr> or something else.
358  if (Tok.is(tok::identifier) &&
359  Tok.getIdentifierInfo()->isStr("omp_priv")) {
360  if (Actions.getLangOpts().CPlusPlus) {
361  InitializerResult = Actions.ActOnFinishFullExpr(
362  ParseAssignmentExpression().get(), D->getLocation(),
363  /*DiscardedValue*/ false);
364  } else {
365  ConsumeToken();
366  ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
367  }
368  } else {
369  InitializerResult = Actions.ActOnFinishFullExpr(
370  ParseAssignmentExpression().get(), D->getLocation(),
371  /*DiscardedValue*/ false);
372  }
373  Actions.ActOnOpenMPDeclareReductionInitializerEnd(
374  D, InitializerResult.get(), OmpPrivParm);
375  if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
376  Tok.isNot(tok::annot_pragma_openmp_end)) {
377  TPA.Commit();
378  IsCorrect = false;
379  break;
380  }
381  IsCorrect =
382  !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
383  }
384  }
385 
386  ++I;
387  // Revert parsing if not the last type, otherwise accept it, we're done with
388  // parsing.
389  if (I != E)
390  TPA.Revert();
391  else
392  TPA.Commit();
393  }
394  return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
395  IsCorrect);
396 }
397 
398 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
399  // Parse declarator '=' initializer.
400  // If a '==' or '+=' is found, suggest a fixit to '='.
401  if (isTokenEqualOrEqualTypo()) {
402  ConsumeToken();
403 
404  if (Tok.is(tok::code_completion)) {
405  Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
406  Actions.FinalizeDeclaration(OmpPrivParm);
407  cutOffParsing();
408  return;
409  }
410 
411  ExprResult Init(ParseInitializer());
412 
413  if (Init.isInvalid()) {
414  SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
415  Actions.ActOnInitializerError(OmpPrivParm);
416  } else {
417  Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
418  /*DirectInit=*/false);
419  }
420  } else if (Tok.is(tok::l_paren)) {
421  // Parse C++ direct initializer: '(' expression-list ')'
422  BalancedDelimiterTracker T(*this, tok::l_paren);
423  T.consumeOpen();
424 
425  ExprVector Exprs;
426  CommaLocsTy CommaLocs;
427 
428  SourceLocation LParLoc = T.getOpenLocation();
429  auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
430  QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
431  getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
432  OmpPrivParm->getLocation(), Exprs, LParLoc);
433  CalledSignatureHelp = true;
434  return PreferredType;
435  };
436  if (ParseExpressionList(Exprs, CommaLocs, [&] {
437  PreferredType.enterFunctionArgument(Tok.getLocation(),
438  RunSignatureHelp);
439  })) {
440  if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
441  RunSignatureHelp();
442  Actions.ActOnInitializerError(OmpPrivParm);
443  SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
444  } else {
445  // Match the ')'.
446  SourceLocation RLoc = Tok.getLocation();
447  if (!T.consumeClose())
448  RLoc = T.getCloseLocation();
449 
450  assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
451  "Unexpected number of commas!");
452 
454  Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
455  Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
456  /*DirectInit=*/true);
457  }
458  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
459  // Parse C++0x braced-init-list.
460  Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
461 
462  ExprResult Init(ParseBraceInitializer());
463 
464  if (Init.isInvalid()) {
465  Actions.ActOnInitializerError(OmpPrivParm);
466  } else {
467  Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
468  /*DirectInit=*/true);
469  }
470  } else {
471  Actions.ActOnUninitializedDecl(OmpPrivParm);
472  }
473 }
474 
475 /// Parses 'omp declare mapper' directive.
476 ///
477 /// declare-mapper-directive:
478 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
479 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
480 /// annot_pragma_openmp_end
481 /// <mapper-identifier> and <var> are base language identifiers.
482 ///
484 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
485  bool IsCorrect = true;
486  // Parse '('
487  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
488  if (T.expectAndConsume(diag::err_expected_lparen_after,
489  getOpenMPDirectiveName(OMPD_declare_mapper))) {
490  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
491  return DeclGroupPtrTy();
492  }
493 
494  // Parse <mapper-identifier>
495  auto &DeclNames = Actions.getASTContext().DeclarationNames;
496  DeclarationName MapperId;
497  if (PP.LookAhead(0).is(tok::colon)) {
498  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
499  Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
500  IsCorrect = false;
501  } else {
502  MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
503  }
504  ConsumeToken();
505  // Consume ':'.
506  ExpectAndConsume(tok::colon);
507  } else {
508  // If no mapper identifier is provided, its name is "default" by default
509  MapperId =
510  DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
511  }
512 
513  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
514  return DeclGroupPtrTy();
515 
516  // Parse <type> <var>
517  DeclarationName VName;
518  QualType MapperType;
519  SourceRange Range;
520  TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
521  if (ParsedType.isUsable())
522  MapperType =
523  Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
524  if (MapperType.isNull())
525  IsCorrect = false;
526  if (!IsCorrect) {
527  SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
528  return DeclGroupPtrTy();
529  }
530 
531  // Consume ')'.
532  IsCorrect &= !T.consumeClose();
533  if (!IsCorrect) {
534  SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
535  return DeclGroupPtrTy();
536  }
537 
538  // Enter scope.
539  OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
540  getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
541  Range.getBegin(), VName, AS);
542  DeclarationNameInfo DirName;
543  SourceLocation Loc = Tok.getLocation();
544  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
546  ParseScope OMPDirectiveScope(this, ScopeFlags);
547  Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
548 
549  // Add the mapper variable declaration.
550  Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
551  DMD, getCurScope(), MapperType, Range.getBegin(), VName);
552 
553  // Parse map clauses.
555  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
556  OpenMPClauseKind CKind = Tok.isAnnotation()
557  ? OMPC_unknown
558  : getOpenMPClauseKind(PP.getSpelling(Tok));
559  Actions.StartOpenMPClause(CKind);
560  OMPClause *Clause =
561  ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
562  if (Clause)
563  Clauses.push_back(Clause);
564  else
565  IsCorrect = false;
566  // Skip ',' if any.
567  if (Tok.is(tok::comma))
568  ConsumeToken();
569  Actions.EndOpenMPClause();
570  }
571  if (Clauses.empty()) {
572  Diag(Tok, diag::err_omp_expected_clause)
573  << getOpenMPDirectiveName(OMPD_declare_mapper);
574  IsCorrect = false;
575  }
576 
577  // Exit scope.
578  Actions.EndOpenMPDSABlock(nullptr);
579  OMPDirectiveScope.Exit();
580 
581  DeclGroupPtrTy DGP =
582  Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
583  if (!IsCorrect)
584  return DeclGroupPtrTy();
585  return DGP;
586 }
587 
588 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
589  DeclarationName &Name,
590  AccessSpecifier AS) {
591  // Parse the common declaration-specifiers piece.
592  Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
593  DeclSpec DS(AttrFactory);
594  ParseSpecifierQualifierList(DS, AS, DSC);
595 
596  // Parse the declarator.
598  Declarator DeclaratorInfo(DS, Context);
599  ParseDeclarator(DeclaratorInfo);
600  Range = DeclaratorInfo.getSourceRange();
601  if (DeclaratorInfo.getIdentifier() == nullptr) {
602  Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
603  return true;
604  }
605  Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
606 
607  return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
608 }
609 
610 namespace {
611 /// RAII that recreates function context for correct parsing of clauses of
612 /// 'declare simd' construct.
613 /// OpenMP, 2.8.2 declare simd Construct
614 /// The expressions appearing in the clauses of this directive are evaluated in
615 /// the scope of the arguments of the function declaration or definition.
616 class FNContextRAII final {
617  Parser &P;
618  Sema::CXXThisScopeRAII *ThisScope;
619  Parser::ParseScope *TempScope;
620  Parser::ParseScope *FnScope;
621  bool HasTemplateScope = false;
622  bool HasFunScope = false;
623  FNContextRAII() = delete;
624  FNContextRAII(const FNContextRAII &) = delete;
625  FNContextRAII &operator=(const FNContextRAII &) = delete;
626 
627 public:
628  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
629  Decl *D = *Ptr.get().begin();
630  NamedDecl *ND = dyn_cast<NamedDecl>(D);
631  RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
632  Sema &Actions = P.getActions();
633 
634  // Allow 'this' within late-parsed attributes.
635  ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
636  ND && ND->isCXXInstanceMember());
637 
638  // If the Decl is templatized, add template parameters to scope.
639  HasTemplateScope = D->isTemplateDecl();
640  TempScope =
641  new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
642  if (HasTemplateScope)
643  Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
644 
645  // If the Decl is on a function, add function parameters to the scope.
646  HasFunScope = D->isFunctionOrFunctionTemplate();
647  FnScope = new Parser::ParseScope(
649  HasFunScope);
650  if (HasFunScope)
651  Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
652  }
653  ~FNContextRAII() {
654  if (HasFunScope) {
656  FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
657  }
658  if (HasTemplateScope)
659  TempScope->Exit();
660  delete FnScope;
661  delete TempScope;
662  delete ThisScope;
663  }
664 };
665 } // namespace
666 
667 /// Parses clauses for 'declare simd' directive.
668 /// clause:
669 /// 'inbranch' | 'notinbranch'
670 /// 'simdlen' '(' <expr> ')'
671 /// { 'uniform' '(' <argument_list> ')' }
672 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
673 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
675  Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
677  SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
678  SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
679  SourceRange BSRange;
680  const Token &Tok = P.getCurToken();
681  bool IsError = false;
682  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
683  if (Tok.isNot(tok::identifier))
684  break;
685  OMPDeclareSimdDeclAttr::BranchStateTy Out;
686  IdentifierInfo *II = Tok.getIdentifierInfo();
687  StringRef ClauseName = II->getName();
688  // Parse 'inranch|notinbranch' clauses.
689  if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
690  if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
691  P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
692  << ClauseName
693  << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
694  IsError = true;
695  }
696  BS = Out;
697  BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
698  P.ConsumeToken();
699  } else if (ClauseName.equals("simdlen")) {
700  if (SimdLen.isUsable()) {
701  P.Diag(Tok, diag::err_omp_more_one_clause)
702  << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
703  IsError = true;
704  }
705  P.ConsumeToken();
706  SourceLocation RLoc;
707  SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
708  if (SimdLen.isInvalid())
709  IsError = true;
710  } else {
711  OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
712  if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
713  CKind == OMPC_linear) {
715  SmallVectorImpl<Expr *> *Vars = &Uniforms;
716  if (CKind == OMPC_aligned)
717  Vars = &Aligneds;
718  else if (CKind == OMPC_linear)
719  Vars = &Linears;
720 
721  P.ConsumeToken();
722  if (P.ParseOpenMPVarList(OMPD_declare_simd,
723  getOpenMPClauseKind(ClauseName), *Vars, Data))
724  IsError = true;
725  if (CKind == OMPC_aligned) {
726  Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
727  } else if (CKind == OMPC_linear) {
729  Data.DepLinMapLoc))
730  Data.LinKind = OMPC_LINEAR_val;
731  LinModifiers.append(Linears.size() - LinModifiers.size(),
732  Data.LinKind);
733  Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
734  }
735  } else
736  // TODO: add parsing of other clauses.
737  break;
738  }
739  // Skip ',' if any.
740  if (Tok.is(tok::comma))
741  P.ConsumeToken();
742  }
743  return IsError;
744 }
745 
746 /// Parse clauses for '#pragma omp declare simd'.
748 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
749  CachedTokens &Toks, SourceLocation Loc) {
750  PP.EnterToken(Tok, /*IsReinject*/ true);
751  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
752  /*IsReinject*/ true);
753  // Consume the previously pushed token.
754  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
755 
756  FNContextRAII FnContext(*this, Ptr);
757  OMPDeclareSimdDeclAttr::BranchStateTy BS =
758  OMPDeclareSimdDeclAttr::BS_Undefined;
759  ExprResult Simdlen;
760  SmallVector<Expr *, 4> Uniforms;
761  SmallVector<Expr *, 4> Aligneds;
762  SmallVector<Expr *, 4> Alignments;
763  SmallVector<Expr *, 4> Linears;
764  SmallVector<unsigned, 4> LinModifiers;
766  bool IsError =
767  parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
768  Alignments, Linears, LinModifiers, Steps);
769  // Need to check for extra tokens.
770  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
771  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
772  << getOpenMPDirectiveName(OMPD_declare_simd);
773  while (Tok.isNot(tok::annot_pragma_openmp_end))
774  ConsumeAnyToken();
775  }
776  // Skip the last annot_pragma_openmp_end.
777  SourceLocation EndLoc = ConsumeAnnotationToken();
778  if (IsError)
779  return Ptr;
780  return Actions.ActOnOpenMPDeclareSimdDirective(
781  Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
782  LinModifiers, Steps, SourceRange(Loc, EndLoc));
783 }
784 
785 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
786  // OpenMP 4.5 syntax with list of entities.
787  Sema::NamedDeclSetType SameDirectiveDecls;
788  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
789  OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
790  if (Tok.is(tok::identifier)) {
791  IdentifierInfo *II = Tok.getIdentifierInfo();
792  StringRef ClauseName = II->getName();
793  // Parse 'to|link' clauses.
794  if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) {
795  Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName;
796  break;
797  }
798  ConsumeToken();
799  }
800  auto &&Callback = [this, MT, &SameDirectiveDecls](
801  CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
802  Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
803  SameDirectiveDecls);
804  };
805  if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
806  /*AllowScopeSpecifier=*/true))
807  break;
808 
809  // Consume optional ','.
810  if (Tok.is(tok::comma))
811  ConsumeToken();
812  }
813  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
814  ConsumeAnyToken();
815  SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
816  SameDirectiveDecls.end());
817  if (Decls.empty())
818  return DeclGroupPtrTy();
819  return Actions.BuildDeclaratorGroup(Decls);
820 }
821 
822 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
823  SourceLocation DTLoc) {
824  if (DKind != OMPD_end_declare_target) {
825  Diag(Tok, diag::err_expected_end_declare_target);
826  Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
827  return;
828  }
829  ConsumeAnyToken();
830  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
831  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
832  << getOpenMPDirectiveName(OMPD_end_declare_target);
833  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
834  }
835  // Skip the last annot_pragma_openmp_end.
836  ConsumeAnyToken();
837 }
838 
839 /// Parsing of declarative OpenMP directives.
840 ///
841 /// threadprivate-directive:
842 /// annot_pragma_openmp 'threadprivate' simple-variable-list
843 /// annot_pragma_openmp_end
844 ///
845 /// allocate-directive:
846 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
847 /// annot_pragma_openmp_end
848 ///
849 /// declare-reduction-directive:
850 /// annot_pragma_openmp 'declare' 'reduction' [...]
851 /// annot_pragma_openmp_end
852 ///
853 /// declare-mapper-directive:
854 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
855 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
856 /// annot_pragma_openmp_end
857 ///
858 /// declare-simd-directive:
859 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
860 /// annot_pragma_openmp_end
861 /// <function declaration/definition>
862 ///
863 /// requires directive:
864 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
865 /// annot_pragma_openmp_end
866 ///
867 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
868  AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
869  DeclSpec::TST TagType, Decl *Tag) {
870  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
871  ParenBraceBracketBalancer BalancerRAIIObj(*this);
872 
873  SourceLocation Loc = ConsumeAnnotationToken();
875 
876  switch (DKind) {
877  case OMPD_threadprivate: {
878  ConsumeToken();
879  DeclDirectiveListParserHelper Helper(this, DKind);
880  if (!ParseOpenMPSimpleVarList(DKind, Helper,
881  /*AllowScopeSpecifier=*/true)) {
882  // The last seen token is annot_pragma_openmp_end - need to check for
883  // extra tokens.
884  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
885  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
886  << getOpenMPDirectiveName(DKind);
887  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
888  }
889  // Skip the last annot_pragma_openmp_end.
890  ConsumeAnnotationToken();
891  return Actions.ActOnOpenMPThreadprivateDirective(Loc,
892  Helper.getIdentifiers());
893  }
894  break;
895  }
896  case OMPD_allocate: {
897  ConsumeToken();
898  DeclDirectiveListParserHelper Helper(this, DKind);
899  if (!ParseOpenMPSimpleVarList(DKind, Helper,
900  /*AllowScopeSpecifier=*/true)) {
902  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
904  OMPC_unknown + 1>
905  FirstClauses(OMPC_unknown + 1);
906  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
907  OpenMPClauseKind CKind =
908  Tok.isAnnotation() ? OMPC_unknown
909  : getOpenMPClauseKind(PP.getSpelling(Tok));
910  Actions.StartOpenMPClause(CKind);
911  OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
912  !FirstClauses[CKind].getInt());
913  SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
914  StopBeforeMatch);
915  FirstClauses[CKind].setInt(true);
916  if (Clause != nullptr)
917  Clauses.push_back(Clause);
918  if (Tok.is(tok::annot_pragma_openmp_end)) {
919  Actions.EndOpenMPClause();
920  break;
921  }
922  // Skip ',' if any.
923  if (Tok.is(tok::comma))
924  ConsumeToken();
925  Actions.EndOpenMPClause();
926  }
927  // The last seen token is annot_pragma_openmp_end - need to check for
928  // extra tokens.
929  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
930  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
931  << getOpenMPDirectiveName(DKind);
932  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
933  }
934  }
935  // Skip the last annot_pragma_openmp_end.
936  ConsumeAnnotationToken();
937  return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
938  Clauses);
939  }
940  break;
941  }
942  case OMPD_requires: {
943  SourceLocation StartLoc = ConsumeToken();
946  FirstClauses(OMPC_unknown + 1);
947  if (Tok.is(tok::annot_pragma_openmp_end)) {
948  Diag(Tok, diag::err_omp_expected_clause)
949  << getOpenMPDirectiveName(OMPD_requires);
950  break;
951  }
952  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
953  OpenMPClauseKind CKind = Tok.isAnnotation()
954  ? OMPC_unknown
955  : getOpenMPClauseKind(PP.getSpelling(Tok));
956  Actions.StartOpenMPClause(CKind);
957  OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
958  !FirstClauses[CKind].getInt());
959  SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
960  StopBeforeMatch);
961  FirstClauses[CKind].setInt(true);
962  if (Clause != nullptr)
963  Clauses.push_back(Clause);
964  if (Tok.is(tok::annot_pragma_openmp_end)) {
965  Actions.EndOpenMPClause();
966  break;
967  }
968  // Skip ',' if any.
969  if (Tok.is(tok::comma))
970  ConsumeToken();
971  Actions.EndOpenMPClause();
972  }
973  // Consume final annot_pragma_openmp_end
974  if (Clauses.size() == 0) {
975  Diag(Tok, diag::err_omp_expected_clause)
976  << getOpenMPDirectiveName(OMPD_requires);
977  ConsumeAnnotationToken();
978  return nullptr;
979  }
980  ConsumeAnnotationToken();
981  return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
982  }
983  case OMPD_declare_reduction:
984  ConsumeToken();
985  if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
986  // The last seen token is annot_pragma_openmp_end - need to check for
987  // extra tokens.
988  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
989  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
990  << getOpenMPDirectiveName(OMPD_declare_reduction);
991  while (Tok.isNot(tok::annot_pragma_openmp_end))
992  ConsumeAnyToken();
993  }
994  // Skip the last annot_pragma_openmp_end.
995  ConsumeAnnotationToken();
996  return Res;
997  }
998  break;
999  case OMPD_declare_mapper: {
1000  ConsumeToken();
1001  if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1002  // Skip the last annot_pragma_openmp_end.
1003  ConsumeAnnotationToken();
1004  return Res;
1005  }
1006  break;
1007  }
1008  case OMPD_declare_simd: {
1009  // The syntax is:
1010  // { #pragma omp declare simd }
1011  // <function-declaration-or-definition>
1012  //
1013  ConsumeToken();
1014  CachedTokens Toks;
1015  while(Tok.isNot(tok::annot_pragma_openmp_end)) {
1016  Toks.push_back(Tok);
1017  ConsumeAnyToken();
1018  }
1019  Toks.push_back(Tok);
1020  ConsumeAnyToken();
1021 
1022  DeclGroupPtrTy Ptr;
1023  if (Tok.is(tok::annot_pragma_openmp)) {
1024  Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
1025  } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1026  // Here we expect to see some function declaration.
1027  if (AS == AS_none) {
1029  MaybeParseCXX11Attributes(Attrs);
1030  ParsingDeclSpec PDS(*this);
1031  Ptr = ParseExternalDeclaration(Attrs, &PDS);
1032  } else {
1033  Ptr =
1034  ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1035  }
1036  }
1037  if (!Ptr) {
1038  Diag(Loc, diag::err_omp_decl_in_declare_simd);
1039  return DeclGroupPtrTy();
1040  }
1041  return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1042  }
1043  case OMPD_declare_target: {
1044  SourceLocation DTLoc = ConsumeAnyToken();
1045  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1046  return ParseOMPDeclareTargetClauses();
1047  }
1048 
1049  // Skip the last annot_pragma_openmp_end.
1050  ConsumeAnyToken();
1051 
1052  if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1053  return DeclGroupPtrTy();
1054 
1056  DKind = parseOpenMPDirectiveKind(*this);
1057  while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1058  Tok.isNot(tok::r_brace)) {
1059  DeclGroupPtrTy Ptr;
1060  // Here we expect to see some function declaration.
1061  if (AS == AS_none) {
1063  MaybeParseCXX11Attributes(Attrs);
1064  ParsingDeclSpec PDS(*this);
1065  Ptr = ParseExternalDeclaration(Attrs, &PDS);
1066  } else {
1067  Ptr =
1068  ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1069  }
1070  if (Ptr) {
1071  DeclGroupRef Ref = Ptr.get();
1072  Decls.append(Ref.begin(), Ref.end());
1073  }
1074  if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
1075  TentativeParsingAction TPA(*this);
1076  ConsumeAnnotationToken();
1077  DKind = parseOpenMPDirectiveKind(*this);
1078  if (DKind != OMPD_end_declare_target)
1079  TPA.Revert();
1080  else
1081  TPA.Commit();
1082  }
1083  }
1084 
1085  ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1086  Actions.ActOnFinishOpenMPDeclareTargetDirective();
1087  return Actions.BuildDeclaratorGroup(Decls);
1088  }
1089  case OMPD_unknown:
1090  Diag(Tok, diag::err_omp_unknown_directive);
1091  break;
1092  case OMPD_parallel:
1093  case OMPD_simd:
1094  case OMPD_task:
1095  case OMPD_taskyield:
1096  case OMPD_barrier:
1097  case OMPD_taskwait:
1098  case OMPD_taskgroup:
1099  case OMPD_flush:
1100  case OMPD_for:
1101  case OMPD_for_simd:
1102  case OMPD_sections:
1103  case OMPD_section:
1104  case OMPD_single:
1105  case OMPD_master:
1106  case OMPD_ordered:
1107  case OMPD_critical:
1108  case OMPD_parallel_for:
1109  case OMPD_parallel_for_simd:
1110  case OMPD_parallel_sections:
1111  case OMPD_atomic:
1112  case OMPD_target:
1113  case OMPD_teams:
1114  case OMPD_cancellation_point:
1115  case OMPD_cancel:
1116  case OMPD_target_data:
1117  case OMPD_target_enter_data:
1118  case OMPD_target_exit_data:
1119  case OMPD_target_parallel:
1120  case OMPD_target_parallel_for:
1121  case OMPD_taskloop:
1122  case OMPD_taskloop_simd:
1123  case OMPD_distribute:
1124  case OMPD_end_declare_target:
1125  case OMPD_target_update:
1126  case OMPD_distribute_parallel_for:
1127  case OMPD_distribute_parallel_for_simd:
1128  case OMPD_distribute_simd:
1129  case OMPD_target_parallel_for_simd:
1130  case OMPD_target_simd:
1131  case OMPD_teams_distribute:
1132  case OMPD_teams_distribute_simd:
1133  case OMPD_teams_distribute_parallel_for_simd:
1134  case OMPD_teams_distribute_parallel_for:
1135  case OMPD_target_teams:
1136  case OMPD_target_teams_distribute:
1137  case OMPD_target_teams_distribute_parallel_for:
1138  case OMPD_target_teams_distribute_parallel_for_simd:
1139  case OMPD_target_teams_distribute_simd:
1140  Diag(Tok, diag::err_omp_unexpected_directive)
1141  << 1 << getOpenMPDirectiveName(DKind);
1142  break;
1143  }
1144  while (Tok.isNot(tok::annot_pragma_openmp_end))
1145  ConsumeAnyToken();
1146  ConsumeAnyToken();
1147  return nullptr;
1148 }
1149 
1150 /// Parsing of declarative or executable OpenMP directives.
1151 ///
1152 /// threadprivate-directive:
1153 /// annot_pragma_openmp 'threadprivate' simple-variable-list
1154 /// annot_pragma_openmp_end
1155 ///
1156 /// allocate-directive:
1157 /// annot_pragma_openmp 'allocate' simple-variable-list
1158 /// annot_pragma_openmp_end
1159 ///
1160 /// declare-reduction-directive:
1161 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
1162 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
1163 /// ('omp_priv' '=' <expression>|<function_call>) ')']
1164 /// annot_pragma_openmp_end
1165 ///
1166 /// declare-mapper-directive:
1167 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1168 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
1169 /// annot_pragma_openmp_end
1170 ///
1171 /// executable-directive:
1172 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
1173 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
1174 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
1175 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
1176 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
1177 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
1178 /// 'distribute' | 'target enter data' | 'target exit data' |
1179 /// 'target parallel' | 'target parallel for' |
1180 /// 'target update' | 'distribute parallel for' |
1181 /// 'distribute paralle for simd' | 'distribute simd' |
1182 /// 'target parallel for simd' | 'target simd' |
1183 /// 'teams distribute' | 'teams distribute simd' |
1184 /// 'teams distribute parallel for simd' |
1185 /// 'teams distribute parallel for' | 'target teams' |
1186 /// 'target teams distribute' |
1187 /// 'target teams distribute parallel for' |
1188 /// 'target teams distribute parallel for simd' |
1189 /// 'target teams distribute simd' {clause}
1190 /// annot_pragma_openmp_end
1191 ///
1192 StmtResult
1193 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1194  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1195  ParenBraceBracketBalancer BalancerRAIIObj(*this);
1198  FirstClauses(OMPC_unknown + 1);
1199  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
1201  SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
1203  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
1204  // Name of critical directive.
1205  DeclarationNameInfo DirName;
1207  bool HasAssociatedStatement = true;
1208  bool FlushHasClause = false;
1209 
1210  switch (DKind) {
1211  case OMPD_threadprivate: {
1212  // FIXME: Should this be permitted in C++?
1213  if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1214  ParsedStmtContext()) {
1215  Diag(Tok, diag::err_omp_immediate_directive)
1216  << getOpenMPDirectiveName(DKind) << 0;
1217  }
1218  ConsumeToken();
1219  DeclDirectiveListParserHelper Helper(this, DKind);
1220  if (!ParseOpenMPSimpleVarList(DKind, Helper,
1221  /*AllowScopeSpecifier=*/false)) {
1222  // The last seen token is annot_pragma_openmp_end - need to check for
1223  // extra tokens.
1224  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1225  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1226  << getOpenMPDirectiveName(DKind);
1227  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1228  }
1229  DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
1230  Loc, Helper.getIdentifiers());
1231  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1232  }
1233  SkipUntil(tok::annot_pragma_openmp_end);
1234  break;
1235  }
1236  case OMPD_allocate: {
1237  // FIXME: Should this be permitted in C++?
1238  if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1239  ParsedStmtContext()) {
1240  Diag(Tok, diag::err_omp_immediate_directive)
1241  << getOpenMPDirectiveName(DKind) << 0;
1242  }
1243  ConsumeToken();
1244  DeclDirectiveListParserHelper Helper(this, DKind);
1245  if (!ParseOpenMPSimpleVarList(DKind, Helper,
1246  /*AllowScopeSpecifier=*/false)) {
1248  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1250  OMPC_unknown + 1>
1251  FirstClauses(OMPC_unknown + 1);
1252  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1253  OpenMPClauseKind CKind =
1254  Tok.isAnnotation() ? OMPC_unknown
1255  : getOpenMPClauseKind(PP.getSpelling(Tok));
1256  Actions.StartOpenMPClause(CKind);
1257  OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1258  !FirstClauses[CKind].getInt());
1259  SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1260  StopBeforeMatch);
1261  FirstClauses[CKind].setInt(true);
1262  if (Clause != nullptr)
1263  Clauses.push_back(Clause);
1264  if (Tok.is(tok::annot_pragma_openmp_end)) {
1265  Actions.EndOpenMPClause();
1266  break;
1267  }
1268  // Skip ',' if any.
1269  if (Tok.is(tok::comma))
1270  ConsumeToken();
1271  Actions.EndOpenMPClause();
1272  }
1273  // The last seen token is annot_pragma_openmp_end - need to check for
1274  // extra tokens.
1275  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1276  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1277  << getOpenMPDirectiveName(DKind);
1278  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1279  }
1280  }
1281  DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
1282  Loc, Helper.getIdentifiers(), Clauses);
1283  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1284  }
1285  SkipUntil(tok::annot_pragma_openmp_end);
1286  break;
1287  }
1288  case OMPD_declare_reduction:
1289  ConsumeToken();
1290  if (DeclGroupPtrTy Res =
1291  ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
1292  // The last seen token is annot_pragma_openmp_end - need to check for
1293  // extra tokens.
1294  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1295  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1296  << getOpenMPDirectiveName(OMPD_declare_reduction);
1297  while (Tok.isNot(tok::annot_pragma_openmp_end))
1298  ConsumeAnyToken();
1299  }
1300  ConsumeAnyToken();
1301  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1302  } else {
1303  SkipUntil(tok::annot_pragma_openmp_end);
1304  }
1305  break;
1306  case OMPD_declare_mapper: {
1307  ConsumeToken();
1308  if (DeclGroupPtrTy Res =
1309  ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
1310  // Skip the last annot_pragma_openmp_end.
1311  ConsumeAnnotationToken();
1312  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1313  } else {
1314  SkipUntil(tok::annot_pragma_openmp_end);
1315  }
1316  break;
1317  }
1318  case OMPD_flush:
1319  if (PP.LookAhead(0).is(tok::l_paren)) {
1320  FlushHasClause = true;
1321  // Push copy of the current token back to stream to properly parse
1322  // pseudo-clause OMPFlushClause.
1323  PP.EnterToken(Tok, /*IsReinject*/ true);
1324  }
1325  LLVM_FALLTHROUGH;
1326  case OMPD_taskyield:
1327  case OMPD_barrier:
1328  case OMPD_taskwait:
1329  case OMPD_cancellation_point:
1330  case OMPD_cancel:
1331  case OMPD_target_enter_data:
1332  case OMPD_target_exit_data:
1333  case OMPD_target_update:
1334  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1335  ParsedStmtContext()) {
1336  Diag(Tok, diag::err_omp_immediate_directive)
1337  << getOpenMPDirectiveName(DKind) << 0;
1338  }
1339  HasAssociatedStatement = false;
1340  // Fall through for further analysis.
1341  LLVM_FALLTHROUGH;
1342  case OMPD_parallel:
1343  case OMPD_simd:
1344  case OMPD_for:
1345  case OMPD_for_simd:
1346  case OMPD_sections:
1347  case OMPD_single:
1348  case OMPD_section:
1349  case OMPD_master:
1350  case OMPD_critical:
1351  case OMPD_parallel_for:
1352  case OMPD_parallel_for_simd:
1353  case OMPD_parallel_sections:
1354  case OMPD_task:
1355  case OMPD_ordered:
1356  case OMPD_atomic:
1357  case OMPD_target:
1358  case OMPD_teams:
1359  case OMPD_taskgroup:
1360  case OMPD_target_data:
1361  case OMPD_target_parallel:
1362  case OMPD_target_parallel_for:
1363  case OMPD_taskloop:
1364  case OMPD_taskloop_simd:
1365  case OMPD_distribute:
1366  case OMPD_distribute_parallel_for:
1367  case OMPD_distribute_parallel_for_simd:
1368  case OMPD_distribute_simd:
1369  case OMPD_target_parallel_for_simd:
1370  case OMPD_target_simd:
1371  case OMPD_teams_distribute:
1372  case OMPD_teams_distribute_simd:
1373  case OMPD_teams_distribute_parallel_for_simd:
1374  case OMPD_teams_distribute_parallel_for:
1375  case OMPD_target_teams:
1376  case OMPD_target_teams_distribute:
1377  case OMPD_target_teams_distribute_parallel_for:
1378  case OMPD_target_teams_distribute_parallel_for_simd:
1379  case OMPD_target_teams_distribute_simd: {
1380  ConsumeToken();
1381  // Parse directive name of the 'critical' directive if any.
1382  if (DKind == OMPD_critical) {
1383  BalancedDelimiterTracker T(*this, tok::l_paren,
1384  tok::annot_pragma_openmp_end);
1385  if (!T.consumeOpen()) {
1386  if (Tok.isAnyIdentifier()) {
1387  DirName =
1388  DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1389  ConsumeAnyToken();
1390  } else {
1391  Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1392  }
1393  T.consumeClose();
1394  }
1395  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1396  CancelRegion = parseOpenMPDirectiveKind(*this);
1397  if (Tok.isNot(tok::annot_pragma_openmp_end))
1398  ConsumeToken();
1399  }
1400 
1401  if (isOpenMPLoopDirective(DKind))
1402  ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1403  if (isOpenMPSimdDirective(DKind))
1404  ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1405  ParseScope OMPDirectiveScope(this, ScopeFlags);
1406  Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1407 
1408  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1409  OpenMPClauseKind CKind =
1410  Tok.isAnnotation()
1411  ? OMPC_unknown
1412  : FlushHasClause ? OMPC_flush
1413  : getOpenMPClauseKind(PP.getSpelling(Tok));
1414  Actions.StartOpenMPClause(CKind);
1415  FlushHasClause = false;
1416  OMPClause *Clause =
1417  ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1418  FirstClauses[CKind].setInt(true);
1419  if (Clause) {
1420  FirstClauses[CKind].setPointer(Clause);
1421  Clauses.push_back(Clause);
1422  }
1423 
1424  // Skip ',' if any.
1425  if (Tok.is(tok::comma))
1426  ConsumeToken();
1427  Actions.EndOpenMPClause();
1428  }
1429  // End location of the directive.
1430  EndLoc = Tok.getLocation();
1431  // Consume final annot_pragma_openmp_end.
1432  ConsumeAnnotationToken();
1433 
1434  // OpenMP [2.13.8, ordered Construct, Syntax]
1435  // If the depend clause is specified, the ordered construct is a stand-alone
1436  // directive.
1437  if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1438  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1439  ParsedStmtContext()) {
1440  Diag(Loc, diag::err_omp_immediate_directive)
1441  << getOpenMPDirectiveName(DKind) << 1
1442  << getOpenMPClauseName(OMPC_depend);
1443  }
1444  HasAssociatedStatement = false;
1445  }
1446 
1447  StmtResult AssociatedStmt;
1448  if (HasAssociatedStatement) {
1449  // The body is a block scope like in Lambdas and Blocks.
1450  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1451  // FIXME: We create a bogus CompoundStmt scope to hold the contents of
1452  // the captured region. Code elsewhere assumes that any FunctionScopeInfo
1453  // should have at least one compound statement scope within it.
1454  AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
1455  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1456  } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1457  DKind == OMPD_target_exit_data) {
1458  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1459  AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
1460  Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
1461  /*isStmtExpr=*/false));
1462  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1463  }
1464  Directive = Actions.ActOnOpenMPExecutableDirective(
1465  DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1466  EndLoc);
1467 
1468  // Exit scope.
1469  Actions.EndOpenMPDSABlock(Directive.get());
1470  OMPDirectiveScope.Exit();
1471  break;
1472  }
1473  case OMPD_declare_simd:
1474  case OMPD_declare_target:
1475  case OMPD_end_declare_target:
1476  case OMPD_requires:
1477  Diag(Tok, diag::err_omp_unexpected_directive)
1478  << 1 << getOpenMPDirectiveName(DKind);
1479  SkipUntil(tok::annot_pragma_openmp_end);
1480  break;
1481  case OMPD_unknown:
1482  Diag(Tok, diag::err_omp_unknown_directive);
1483  SkipUntil(tok::annot_pragma_openmp_end);
1484  break;
1485  }
1486  return Directive;
1487 }
1488 
1489 // Parses simple list:
1490 // simple-variable-list:
1491 // '(' id-expression {, id-expression} ')'
1492 //
1493 bool Parser::ParseOpenMPSimpleVarList(
1495  const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1496  Callback,
1497  bool AllowScopeSpecifier) {
1498  // Parse '('.
1499  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1500  if (T.expectAndConsume(diag::err_expected_lparen_after,
1502  return true;
1503  bool IsCorrect = true;
1504  bool NoIdentIsFound = true;
1505 
1506  // Read tokens while ')' or annot_pragma_openmp_end is not found.
1507  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1508  CXXScopeSpec SS;
1509  UnqualifiedId Name;
1510  // Read var name.
1511  Token PrevTok = Tok;
1512  NoIdentIsFound = false;
1513 
1514  if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1515  ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1516  IsCorrect = false;
1517  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1518  StopBeforeMatch);
1519  } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1520  nullptr, Name)) {
1521  IsCorrect = false;
1522  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1523  StopBeforeMatch);
1524  } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1525  Tok.isNot(tok::annot_pragma_openmp_end)) {
1526  IsCorrect = false;
1527  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1528  StopBeforeMatch);
1529  Diag(PrevTok.getLocation(), diag::err_expected)
1530  << tok::identifier
1531  << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1532  } else {
1533  Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1534  }
1535  // Consume ','.
1536  if (Tok.is(tok::comma)) {
1537  ConsumeToken();
1538  }
1539  }
1540 
1541  if (NoIdentIsFound) {
1542  Diag(Tok, diag::err_expected) << tok::identifier;
1543  IsCorrect = false;
1544  }
1545 
1546  // Parse ')'.
1547  IsCorrect = !T.consumeClose() && IsCorrect;
1548 
1549  return !IsCorrect;
1550 }
1551 
1552 /// Parsing of OpenMP clauses.
1553 ///
1554 /// clause:
1555 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1556 /// default-clause | private-clause | firstprivate-clause | shared-clause
1557 /// | linear-clause | aligned-clause | collapse-clause |
1558 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1559 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1560 /// mergeable-clause | flush-clause | read-clause | write-clause |
1561 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1562 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1563 /// thread_limit-clause | priority-clause | grainsize-clause |
1564 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1565 /// from-clause | is_device_ptr-clause | task_reduction-clause |
1566 /// in_reduction-clause | allocator-clause | allocate-clause
1567 ///
1568 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1569  OpenMPClauseKind CKind, bool FirstClause) {
1570  OMPClause *Clause = nullptr;
1571  bool ErrorFound = false;
1572  bool WrongDirective = false;
1573  // Check if clause is allowed for the given directive.
1574  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1575  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1576  << getOpenMPDirectiveName(DKind);
1577  ErrorFound = true;
1578  WrongDirective = true;
1579  }
1580 
1581  switch (CKind) {
1582  case OMPC_final:
1583  case OMPC_num_threads:
1584  case OMPC_safelen:
1585  case OMPC_simdlen:
1586  case OMPC_collapse:
1587  case OMPC_ordered:
1588  case OMPC_device:
1589  case OMPC_num_teams:
1590  case OMPC_thread_limit:
1591  case OMPC_priority:
1592  case OMPC_grainsize:
1593  case OMPC_num_tasks:
1594  case OMPC_hint:
1595  case OMPC_allocator:
1596  // OpenMP [2.5, Restrictions]
1597  // At most one num_threads clause can appear on the directive.
1598  // OpenMP [2.8.1, simd construct, Restrictions]
1599  // Only one safelen clause can appear on a simd directive.
1600  // Only one simdlen clause can appear on a simd directive.
1601  // Only one collapse clause can appear on a simd directive.
1602  // OpenMP [2.9.1, target data construct, Restrictions]
1603  // At most one device clause can appear on the directive.
1604  // OpenMP [2.11.1, task Construct, Restrictions]
1605  // At most one if clause can appear on the directive.
1606  // At most one final clause can appear on the directive.
1607  // OpenMP [teams Construct, Restrictions]
1608  // At most one num_teams clause can appear on the directive.
1609  // At most one thread_limit clause can appear on the directive.
1610  // OpenMP [2.9.1, task Construct, Restrictions]
1611  // At most one priority clause can appear on the directive.
1612  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1613  // At most one grainsize clause can appear on the directive.
1614  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1615  // At most one num_tasks clause can appear on the directive.
1616  // OpenMP [2.11.3, allocate Directive, Restrictions]
1617  // At most one allocator clause can appear on the directive.
1618  if (!FirstClause) {
1619  Diag(Tok, diag::err_omp_more_one_clause)
1620  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1621  ErrorFound = true;
1622  }
1623 
1624  if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1625  Clause = ParseOpenMPClause(CKind, WrongDirective);
1626  else
1627  Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
1628  break;
1629  case OMPC_default:
1630  case OMPC_proc_bind:
1631  case OMPC_atomic_default_mem_order:
1632  // OpenMP [2.14.3.1, Restrictions]
1633  // Only a single default clause may be specified on a parallel, task or
1634  // teams directive.
1635  // OpenMP [2.5, parallel Construct, Restrictions]
1636  // At most one proc_bind clause can appear on the directive.
1637  // OpenMP [5.0, Requires directive, Restrictions]
1638  // At most one atomic_default_mem_order clause can appear
1639  // on the directive
1640  if (!FirstClause) {
1641  Diag(Tok, diag::err_omp_more_one_clause)
1642  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1643  ErrorFound = true;
1644  }
1645 
1646  Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
1647  break;
1648  case OMPC_schedule:
1649  case OMPC_dist_schedule:
1650  case OMPC_defaultmap:
1651  // OpenMP [2.7.1, Restrictions, p. 3]
1652  // Only one schedule clause can appear on a loop directive.
1653  // OpenMP [2.10.4, Restrictions, p. 106]
1654  // At most one defaultmap clause can appear on the directive.
1655  if (!FirstClause) {
1656  Diag(Tok, diag::err_omp_more_one_clause)
1657  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1658  ErrorFound = true;
1659  }
1660  LLVM_FALLTHROUGH;
1661 
1662  case OMPC_if:
1663  Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
1664  break;
1665  case OMPC_nowait:
1666  case OMPC_untied:
1667  case OMPC_mergeable:
1668  case OMPC_read:
1669  case OMPC_write:
1670  case OMPC_update:
1671  case OMPC_capture:
1672  case OMPC_seq_cst:
1673  case OMPC_threads:
1674  case OMPC_simd:
1675  case OMPC_nogroup:
1676  case OMPC_unified_address:
1677  case OMPC_unified_shared_memory:
1678  case OMPC_reverse_offload:
1679  case OMPC_dynamic_allocators:
1680  // OpenMP [2.7.1, Restrictions, p. 9]
1681  // Only one ordered clause can appear on a loop directive.
1682  // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1683  // Only one nowait clause can appear on a for directive.
1684  // OpenMP [5.0, Requires directive, Restrictions]
1685  // Each of the requires clauses can appear at most once on the directive.
1686  if (!FirstClause) {
1687  Diag(Tok, diag::err_omp_more_one_clause)
1688  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1689  ErrorFound = true;
1690  }
1691 
1692  Clause = ParseOpenMPClause(CKind, WrongDirective);
1693  break;
1694  case OMPC_private:
1695  case OMPC_firstprivate:
1696  case OMPC_lastprivate:
1697  case OMPC_shared:
1698  case OMPC_reduction:
1699  case OMPC_task_reduction:
1700  case OMPC_in_reduction:
1701  case OMPC_linear:
1702  case OMPC_aligned:
1703  case OMPC_copyin:
1704  case OMPC_copyprivate:
1705  case OMPC_flush:
1706  case OMPC_depend:
1707  case OMPC_map:
1708  case OMPC_to:
1709  case OMPC_from:
1710  case OMPC_use_device_ptr:
1711  case OMPC_is_device_ptr:
1712  case OMPC_allocate:
1713  Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
1714  break;
1715  case OMPC_unknown:
1716  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1717  << getOpenMPDirectiveName(DKind);
1718  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1719  break;
1720  case OMPC_threadprivate:
1721  case OMPC_uniform:
1722  if (!WrongDirective)
1723  Diag(Tok, diag::err_omp_unexpected_clause)
1724  << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
1725  SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1726  break;
1727  }
1728  return ErrorFound ? nullptr : Clause;
1729 }
1730 
1731 /// Parses simple expression in parens for single-expression clauses of OpenMP
1732 /// constructs.
1733 /// \param RLoc Returned location of right paren.
1735  SourceLocation &RLoc) {
1736  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1737  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1738  return ExprError();
1739 
1740  SourceLocation ELoc = Tok.getLocation();
1741  ExprResult LHS(ParseCastExpression(
1742  /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1743  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1744  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
1745 
1746  // Parse ')'.
1747  RLoc = Tok.getLocation();
1748  if (!T.consumeClose())
1749  RLoc = T.getCloseLocation();
1750 
1751  return Val;
1752 }
1753 
1754 /// Parsing of OpenMP clauses with single expressions like 'final',
1755 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1756 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1757 ///
1758 /// final-clause:
1759 /// 'final' '(' expression ')'
1760 ///
1761 /// num_threads-clause:
1762 /// 'num_threads' '(' expression ')'
1763 ///
1764 /// safelen-clause:
1765 /// 'safelen' '(' expression ')'
1766 ///
1767 /// simdlen-clause:
1768 /// 'simdlen' '(' expression ')'
1769 ///
1770 /// collapse-clause:
1771 /// 'collapse' '(' expression ')'
1772 ///
1773 /// priority-clause:
1774 /// 'priority' '(' expression ')'
1775 ///
1776 /// grainsize-clause:
1777 /// 'grainsize' '(' expression ')'
1778 ///
1779 /// num_tasks-clause:
1780 /// 'num_tasks' '(' expression ')'
1781 ///
1782 /// hint-clause:
1783 /// 'hint' '(' expression ')'
1784 ///
1785 /// allocator-clause:
1786 /// 'allocator' '(' expression ')'
1787 ///
1788 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
1789  bool ParseOnly) {
1790  SourceLocation Loc = ConsumeToken();
1791  SourceLocation LLoc = Tok.getLocation();
1792  SourceLocation RLoc;
1793 
1794  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1795 
1796  if (Val.isInvalid())
1797  return nullptr;
1798 
1799  if (ParseOnly)
1800  return nullptr;
1801  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1802 }
1803 
1804 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1805 ///
1806 /// default-clause:
1807 /// 'default' '(' 'none' | 'shared' ')
1808 ///
1809 /// proc_bind-clause:
1810 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1811 ///
1812 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
1813  bool ParseOnly) {
1814  SourceLocation Loc = Tok.getLocation();
1815  SourceLocation LOpen = ConsumeToken();
1816  // Parse '('.
1817  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1818  if (T.expectAndConsume(diag::err_expected_lparen_after,
1820  return nullptr;
1821 
1822  unsigned Type = getOpenMPSimpleClauseType(
1823  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1824  SourceLocation TypeLoc = Tok.getLocation();
1825  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1826  Tok.isNot(tok::annot_pragma_openmp_end))
1827  ConsumeAnyToken();
1828 
1829  // Parse ')'.
1830  SourceLocation RLoc = Tok.getLocation();
1831  if (!T.consumeClose())
1832  RLoc = T.getCloseLocation();
1833 
1834  if (ParseOnly)
1835  return nullptr;
1836  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
1837 }
1838 
1839 /// Parsing of OpenMP clauses like 'ordered'.
1840 ///
1841 /// ordered-clause:
1842 /// 'ordered'
1843 ///
1844 /// nowait-clause:
1845 /// 'nowait'
1846 ///
1847 /// untied-clause:
1848 /// 'untied'
1849 ///
1850 /// mergeable-clause:
1851 /// 'mergeable'
1852 ///
1853 /// read-clause:
1854 /// 'read'
1855 ///
1856 /// threads-clause:
1857 /// 'threads'
1858 ///
1859 /// simd-clause:
1860 /// 'simd'
1861 ///
1862 /// nogroup-clause:
1863 /// 'nogroup'
1864 ///
1865 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
1866  SourceLocation Loc = Tok.getLocation();
1867  ConsumeAnyToken();
1868 
1869  if (ParseOnly)
1870  return nullptr;
1871  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1872 }
1873 
1874 
1875 /// Parsing of OpenMP clauses with single expressions and some additional
1876 /// argument like 'schedule' or 'dist_schedule'.
1877 ///
1878 /// schedule-clause:
1879 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1880 /// ')'
1881 ///
1882 /// if-clause:
1883 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1884 ///
1885 /// defaultmap:
1886 /// 'defaultmap' '(' modifier ':' kind ')'
1887 ///
1888 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
1889  bool ParseOnly) {
1890  SourceLocation Loc = ConsumeToken();
1891  SourceLocation DelimLoc;
1892  // Parse '('.
1893  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1894  if (T.expectAndConsume(diag::err_expected_lparen_after,
1896  return nullptr;
1897 
1898  ExprResult Val;
1901  if (Kind == OMPC_schedule) {
1902  enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1903  Arg.resize(NumberOfElements);
1904  KLoc.resize(NumberOfElements);
1905  Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1906  Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1907  Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1908  unsigned KindModifier = getOpenMPSimpleClauseType(
1909  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1910  if (KindModifier > OMPC_SCHEDULE_unknown) {
1911  // Parse 'modifier'
1912  Arg[Modifier1] = KindModifier;
1913  KLoc[Modifier1] = Tok.getLocation();
1914  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1915  Tok.isNot(tok::annot_pragma_openmp_end))
1916  ConsumeAnyToken();
1917  if (Tok.is(tok::comma)) {
1918  // Parse ',' 'modifier'
1919  ConsumeAnyToken();
1920  KindModifier = getOpenMPSimpleClauseType(
1921  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1922  Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1923  ? KindModifier
1924  : (unsigned)OMPC_SCHEDULE_unknown;
1925  KLoc[Modifier2] = Tok.getLocation();
1926  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1927  Tok.isNot(tok::annot_pragma_openmp_end))
1928  ConsumeAnyToken();
1929  }
1930  // Parse ':'
1931  if (Tok.is(tok::colon))
1932  ConsumeAnyToken();
1933  else
1934  Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1935  KindModifier = getOpenMPSimpleClauseType(
1936  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1937  }
1938  Arg[ScheduleKind] = KindModifier;
1939  KLoc[ScheduleKind] = Tok.getLocation();
1940  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1941  Tok.isNot(tok::annot_pragma_openmp_end))
1942  ConsumeAnyToken();
1943  if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1944  Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1945  Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1946  Tok.is(tok::comma))
1947  DelimLoc = ConsumeAnyToken();
1948  } else if (Kind == OMPC_dist_schedule) {
1949  Arg.push_back(getOpenMPSimpleClauseType(
1950  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1951  KLoc.push_back(Tok.getLocation());
1952  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1953  Tok.isNot(tok::annot_pragma_openmp_end))
1954  ConsumeAnyToken();
1955  if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1956  DelimLoc = ConsumeAnyToken();
1957  } else if (Kind == OMPC_defaultmap) {
1958  // Get a defaultmap modifier
1959  Arg.push_back(getOpenMPSimpleClauseType(
1960  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1961  KLoc.push_back(Tok.getLocation());
1962  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1963  Tok.isNot(tok::annot_pragma_openmp_end))
1964  ConsumeAnyToken();
1965  // Parse ':'
1966  if (Tok.is(tok::colon))
1967  ConsumeAnyToken();
1968  else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1969  Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1970  // Get a defaultmap kind
1971  Arg.push_back(getOpenMPSimpleClauseType(
1972  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1973  KLoc.push_back(Tok.getLocation());
1974  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1975  Tok.isNot(tok::annot_pragma_openmp_end))
1976  ConsumeAnyToken();
1977  } else {
1978  assert(Kind == OMPC_if);
1979  KLoc.push_back(Tok.getLocation());
1980  TentativeParsingAction TPA(*this);
1981  Arg.push_back(parseOpenMPDirectiveKind(*this));
1982  if (Arg.back() != OMPD_unknown) {
1983  ConsumeToken();
1984  if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1985  TPA.Commit();
1986  DelimLoc = ConsumeToken();
1987  } else {
1988  TPA.Revert();
1989  Arg.back() = OMPD_unknown;
1990  }
1991  } else {
1992  TPA.Revert();
1993  }
1994  }
1995 
1996  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1997  (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1998  Kind == OMPC_if;
1999  if (NeedAnExpression) {
2000  SourceLocation ELoc = Tok.getLocation();
2001  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
2002  Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
2003  Val =
2004  Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2005  }
2006 
2007  // Parse ')'.
2008  SourceLocation RLoc = Tok.getLocation();
2009  if (!T.consumeClose())
2010  RLoc = T.getCloseLocation();
2011 
2012  if (NeedAnExpression && Val.isInvalid())
2013  return nullptr;
2014 
2015  if (ParseOnly)
2016  return nullptr;
2017  return Actions.ActOnOpenMPSingleExprWithArgClause(
2018  Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
2019 }
2020 
2021 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
2022  UnqualifiedId &ReductionId) {
2023  if (ReductionIdScopeSpec.isEmpty()) {
2024  auto OOK = OO_None;
2025  switch (P.getCurToken().getKind()) {
2026  case tok::plus:
2027  OOK = OO_Plus;
2028  break;
2029  case tok::minus:
2030  OOK = OO_Minus;
2031  break;
2032  case tok::star:
2033  OOK = OO_Star;
2034  break;
2035  case tok::amp:
2036  OOK = OO_Amp;
2037  break;
2038  case tok::pipe:
2039  OOK = OO_Pipe;
2040  break;
2041  case tok::caret:
2042  OOK = OO_Caret;
2043  break;
2044  case tok::ampamp:
2045  OOK = OO_AmpAmp;
2046  break;
2047  case tok::pipepipe:
2048  OOK = OO_PipePipe;
2049  break;
2050  default:
2051  break;
2052  }
2053  if (OOK != OO_None) {
2054  SourceLocation OpLoc = P.ConsumeToken();
2055  SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
2056  ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
2057  return false;
2058  }
2059  }
2060  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
2061  /*AllowDestructorName*/ false,
2062  /*AllowConstructorName*/ false,
2063  /*AllowDeductionGuide*/ false,
2064  nullptr, nullptr, ReductionId);
2065 }
2066 
2067 /// Checks if the token is a valid map-type-modifier.
2069  Token Tok = P.getCurToken();
2070  if (!Tok.is(tok::identifier))
2072 
2073  Preprocessor &PP = P.getPreprocessor();
2074  OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
2075  getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2076  return TypeModifier;
2077 }
2078 
2079 /// Parse the mapper modifier in map, to, and from clauses.
2081  // Parse '('.
2082  BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
2083  if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
2084  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2085  StopBeforeMatch);
2086  return true;
2087  }
2088  // Parse mapper-identifier
2089  if (getLangOpts().CPlusPlus)
2090  ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2091  /*ObjectType=*/nullptr,
2092  /*EnteringContext=*/false);
2093  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
2094  Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
2095  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2096  StopBeforeMatch);
2097  return true;
2098  }
2099  auto &DeclNames = Actions.getASTContext().DeclarationNames;
2101  DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
2102  ConsumeToken();
2103  // Parse ')'.
2104  return T.consumeClose();
2105 }
2106 
2107 /// Parse map-type-modifiers in map clause.
2108 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2109 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
2111  while (getCurToken().isNot(tok::colon)) {
2112  OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
2113  if (TypeModifier == OMPC_MAP_MODIFIER_always ||
2114  TypeModifier == OMPC_MAP_MODIFIER_close) {
2115  Data.MapTypeModifiers.push_back(TypeModifier);
2116  Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2117  ConsumeToken();
2118  } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
2119  Data.MapTypeModifiers.push_back(TypeModifier);
2120  Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2121  ConsumeToken();
2122  if (parseMapperModifier(Data))
2123  return true;
2124  } else {
2125  // For the case of unknown map-type-modifier or a map-type.
2126  // Map-type is followed by a colon; the function returns when it
2127  // encounters a token followed by a colon.
2128  if (Tok.is(tok::comma)) {
2129  Diag(Tok, diag::err_omp_map_type_modifier_missing);
2130  ConsumeToken();
2131  continue;
2132  }
2133  // Potential map-type token as it is followed by a colon.
2134  if (PP.LookAhead(0).is(tok::colon))
2135  return false;
2136  Diag(Tok, diag::err_omp_unknown_map_type_modifier);
2137  ConsumeToken();
2138  }
2139  if (getCurToken().is(tok::comma))
2140  ConsumeToken();
2141  }
2142  return false;
2143 }
2144 
2145 /// Checks if the token is a valid map-type.
2147  Token Tok = P.getCurToken();
2148  // The map-type token can be either an identifier or the C++ delete keyword.
2149  if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
2150  return OMPC_MAP_unknown;
2151  Preprocessor &PP = P.getPreprocessor();
2152  OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
2153  getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2154  return MapType;
2155 }
2156 
2157 /// Parse map-type in map clause.
2158 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2159 /// where, map-type ::= to | from | tofrom | alloc | release | delete
2161  Token Tok = P.getCurToken();
2162  if (Tok.is(tok::colon)) {
2163  P.Diag(Tok, diag::err_omp_map_type_missing);
2164  return;
2165  }
2166  Data.MapType = isMapType(P);
2167  if (Data.MapType == OMPC_MAP_unknown)
2168  P.Diag(Tok, diag::err_omp_unknown_map_type);
2169  P.ConsumeToken();
2170 }
2171 
2172 /// Parses clauses with list.
2176  OpenMPVarListDataTy &Data) {
2177  UnqualifiedId UnqualifiedReductionId;
2178  bool InvalidReductionId = false;
2179  bool IsInvalidMapperModifier = false;
2180 
2181  // Parse '('.
2182  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2183  if (T.expectAndConsume(diag::err_expected_lparen_after,
2184  getOpenMPClauseName(Kind)))
2185  return true;
2186 
2187  bool NeedRParenForLinear = false;
2188  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
2189  tok::annot_pragma_openmp_end);
2190  // Handle reduction-identifier for reduction clause.
2191  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
2192  Kind == OMPC_in_reduction) {
2193  ColonProtectionRAIIObject ColonRAII(*this);
2194  if (getLangOpts().CPlusPlus)
2195  ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2196  /*ObjectType=*/nullptr,
2197  /*EnteringContext=*/false);
2198  InvalidReductionId = ParseReductionId(
2199  *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
2200  if (InvalidReductionId) {
2201  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2202  StopBeforeMatch);
2203  }
2204  if (Tok.is(tok::colon))
2205  Data.ColonLoc = ConsumeToken();
2206  else
2207  Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
2208  if (!InvalidReductionId)
2209  Data.ReductionOrMapperId =
2210  Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
2211  } else if (Kind == OMPC_depend) {
2212  // Handle dependency type for depend clause.
2213  ColonProtectionRAIIObject ColonRAII(*this);
2214  Data.DepKind =
2216  Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
2217  Data.DepLinMapLoc = Tok.getLocation();
2218 
2219  if (Data.DepKind == OMPC_DEPEND_unknown) {
2220  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2221  StopBeforeMatch);
2222  } else {
2223  ConsumeToken();
2224  // Special processing for depend(source) clause.
2225  if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
2226  // Parse ')'.
2227  T.consumeClose();
2228  return false;
2229  }
2230  }
2231  if (Tok.is(tok::colon)) {
2232  Data.ColonLoc = ConsumeToken();
2233  } else {
2234  Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
2235  : diag::warn_pragma_expected_colon)
2236  << "dependency type";
2237  }
2238  } else if (Kind == OMPC_linear) {
2239  // Try to parse modifier if any.
2240  if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
2241  Data.LinKind = static_cast<OpenMPLinearClauseKind>(
2242  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2243  Data.DepLinMapLoc = ConsumeToken();
2244  LinearT.consumeOpen();
2245  NeedRParenForLinear = true;
2246  }
2247  } else if (Kind == OMPC_map) {
2248  // Handle map type for map clause.
2249  ColonProtectionRAIIObject ColonRAII(*this);
2250 
2251  // The first identifier may be a list item, a map-type or a
2252  // map-type-modifier. The map-type can also be delete which has the same
2253  // spelling of the C++ delete keyword.
2254  Data.DepLinMapLoc = Tok.getLocation();
2255 
2256  // Check for presence of a colon in the map clause.
2257  TentativeParsingAction TPA(*this);
2258  bool ColonPresent = false;
2259  if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2260  StopBeforeMatch)) {
2261  if (Tok.is(tok::colon))
2262  ColonPresent = true;
2263  }
2264  TPA.Revert();
2265  // Only parse map-type-modifier[s] and map-type if a colon is present in
2266  // the map clause.
2267  if (ColonPresent) {
2268  IsInvalidMapperModifier = parseMapTypeModifiers(Data);
2269  if (!IsInvalidMapperModifier)
2270  parseMapType(*this, Data);
2271  else
2272  SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
2273  }
2274  if (Data.MapType == OMPC_MAP_unknown) {
2275  Data.MapType = OMPC_MAP_tofrom;
2276  Data.IsMapTypeImplicit = true;
2277  }
2278 
2279  if (Tok.is(tok::colon))
2280  Data.ColonLoc = ConsumeToken();
2281  } else if (Kind == OMPC_to || Kind == OMPC_from) {
2282  if (Tok.is(tok::identifier)) {
2283  bool IsMapperModifier = false;
2284  if (Kind == OMPC_to) {
2285  auto Modifier = static_cast<OpenMPToModifierKind>(
2286  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2287  if (Modifier == OMPC_TO_MODIFIER_mapper)
2288  IsMapperModifier = true;
2289  } else {
2290  auto Modifier = static_cast<OpenMPFromModifierKind>(
2291  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2292  if (Modifier == OMPC_FROM_MODIFIER_mapper)
2293  IsMapperModifier = true;
2294  }
2295  if (IsMapperModifier) {
2296  // Parse the mapper modifier.
2297  ConsumeToken();
2298  IsInvalidMapperModifier = parseMapperModifier(Data);
2299  if (Tok.isNot(tok::colon)) {
2300  if (!IsInvalidMapperModifier)
2301  Diag(Tok, diag::warn_pragma_expected_colon) << ")";
2302  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2303  StopBeforeMatch);
2304  }
2305  // Consume ':'.
2306  if (Tok.is(tok::colon))
2307  ConsumeToken();
2308  }
2309  }
2310  } else if (Kind == OMPC_allocate) {
2311  // Handle optional allocator expression followed by colon delimiter.
2312  ColonProtectionRAIIObject ColonRAII(*this);
2313  TentativeParsingAction TPA(*this);
2314  ExprResult Tail =
2315  Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2316  Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
2317  /*DiscardedValue=*/false);
2318  if (Tail.isUsable()) {
2319  if (Tok.is(tok::colon)) {
2320  Data.TailExpr = Tail.get();
2321  Data.ColonLoc = ConsumeToken();
2322  TPA.Commit();
2323  } else {
2324  // colon not found, no allocator specified, parse only list of
2325  // variables.
2326  TPA.Revert();
2327  }
2328  } else {
2329  // Parsing was unsuccessfull, revert and skip to the end of clause or
2330  // directive.
2331  TPA.Revert();
2332  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2333  StopBeforeMatch);
2334  }
2335  }
2336 
2337  bool IsComma =
2338  (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
2339  Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
2340  (Kind == OMPC_reduction && !InvalidReductionId) ||
2341  (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
2342  (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
2343  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
2344  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
2345  Tok.isNot(tok::annot_pragma_openmp_end))) {
2346  ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
2347  // Parse variable
2348  ExprResult VarExpr =
2349  Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2350  if (VarExpr.isUsable()) {
2351  Vars.push_back(VarExpr.get());
2352  } else {
2353  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2354  StopBeforeMatch);
2355  }
2356  // Skip ',' if any
2357  IsComma = Tok.is(tok::comma);
2358  if (IsComma)
2359  ConsumeToken();
2360  else if (Tok.isNot(tok::r_paren) &&
2361  Tok.isNot(tok::annot_pragma_openmp_end) &&
2362  (!MayHaveTail || Tok.isNot(tok::colon)))
2363  Diag(Tok, diag::err_omp_expected_punc)
2364  << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
2365  : getOpenMPClauseName(Kind))
2366  << (Kind == OMPC_flush);
2367  }
2368 
2369  // Parse ')' for linear clause with modifier.
2370  if (NeedRParenForLinear)
2371  LinearT.consumeClose();
2372 
2373  // Parse ':' linear-step (or ':' alignment).
2374  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
2375  if (MustHaveTail) {
2376  Data.ColonLoc = Tok.getLocation();
2377  SourceLocation ELoc = ConsumeToken();
2378  ExprResult Tail = ParseAssignmentExpression();
2379  Tail =
2380  Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
2381  if (Tail.isUsable())
2382  Data.TailExpr = Tail.get();
2383  else
2384  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2385  StopBeforeMatch);
2386  }
2387 
2388  // Parse ')'.
2389  Data.RLoc = Tok.getLocation();
2390  if (!T.consumeClose())
2391  Data.RLoc = T.getCloseLocation();
2392  return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
2393  Vars.empty()) ||
2394  (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
2395  (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
2396  IsInvalidMapperModifier;
2397 }
2398 
2399 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
2400 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
2401 /// 'in_reduction'.
2402 ///
2403 /// private-clause:
2404 /// 'private' '(' list ')'
2405 /// firstprivate-clause:
2406 /// 'firstprivate' '(' list ')'
2407 /// lastprivate-clause:
2408 /// 'lastprivate' '(' list ')'
2409 /// shared-clause:
2410 /// 'shared' '(' list ')'
2411 /// linear-clause:
2412 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
2413 /// aligned-clause:
2414 /// 'aligned' '(' list [ ':' alignment ] ')'
2415 /// reduction-clause:
2416 /// 'reduction' '(' reduction-identifier ':' list ')'
2417 /// task_reduction-clause:
2418 /// 'task_reduction' '(' reduction-identifier ':' list ')'
2419 /// in_reduction-clause:
2420 /// 'in_reduction' '(' reduction-identifier ':' list ')'
2421 /// copyprivate-clause:
2422 /// 'copyprivate' '(' list ')'
2423 /// flush-clause:
2424 /// 'flush' '(' list ')'
2425 /// depend-clause:
2426 /// 'depend' '(' in | out | inout : list | source ')'
2427 /// map-clause:
2428 /// 'map' '(' [ [ always [,] ] [ close [,] ]
2429 /// [ mapper '(' mapper-identifier ')' [,] ]
2430 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
2431 /// to-clause:
2432 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2433 /// from-clause:
2434 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2435 /// use_device_ptr-clause:
2436 /// 'use_device_ptr' '(' list ')'
2437 /// is_device_ptr-clause:
2438 /// 'is_device_ptr' '(' list ')'
2439 /// allocate-clause:
2440 /// 'allocate' '(' [ allocator ':' ] list ')'
2441 ///
2442 /// For 'linear' clause linear-list may have the following forms:
2443 /// list
2444 /// modifier(list)
2445 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
2446 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
2448  bool ParseOnly) {
2449  SourceLocation Loc = Tok.getLocation();
2450  SourceLocation LOpen = ConsumeToken();
2452  OpenMPVarListDataTy Data;
2453 
2454  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
2455  return nullptr;
2456 
2457  if (ParseOnly)
2458  return nullptr;
2459  OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
2460  return Actions.ActOnOpenMPVarListClause(
2461  Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
2463  Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
2464  Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc);
2465 }
2466 
OpenMPDependClauseKind DepKind
Definition: Parser.h:2939
OpenMPFromModifierKind
OpenMP modifier kind for &#39;from&#39; clause.
Definition: OpenMPKinds.h:116
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:995
A (possibly-)qualified type.
Definition: Type.h:643
static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P)
Definition: ParseOpenMP.cpp:86
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:2938
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:2942
StringRef P
The base class of the type hierarchy.
Definition: Type.h:1421
SourceLocation getCloseLocation() const
This indicates that the scope corresponds to a function, which means that labels are set here...
Definition: Scope.h:47
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind)
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:112
void ActOnExitFunctionContext()
Definition: SemaDecl.cpp:1337
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.
Represents a variable declaration or definition.
Definition: Decl.h:812
ActionResult< Stmt * > StmtResult
Definition: Ownership.h:264
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1775
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:59
RAII object used to temporarily allow the C++ &#39;this&#39; expression to be used, with the given qualifiers...
Definition: Sema.h:5324
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
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:1089
OpenMPLinearClauseKind LinKind
Definition: Parser.h:2940
The collection of all-type qualifiers we support.
Definition: Type.h:137
OpenMPMapModifierKind
OpenMP modifier kind for &#39;map&#39; clause.
Definition: OpenMPKinds.h:99
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:56
Represents a struct/union/class.
Definition: Decl.h:3626
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
Definition: OpenMPKinds.cpp:61
One of these records is kept for each identifier that is lexed.
OpenMPLinearClauseKind
OpenMP attributes for &#39;linear&#39; clause.
Definition: OpenMPKinds.h:83
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 { ...
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:944
PtrTy get() const
Definition: Ownership.h:170
bool isNot(T Kind) const
Definition: FormatToken.h:328
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 ...
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.
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
IdentifierInfo * getIdentifier() const
Definition: DeclSpec.h:2137
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:328
A RAII object to enter scope of a compound statement.
Definition: Sema.h:3858
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:572
This is the scope of OpenMP executable directive.
Definition: Scope.h:107
Sema & getActions() const
Definition: Parser.h:406
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.
const Token & getCurToken() const
Definition: Parser.h:409
OpenMPDirectiveKindEx
Definition: ParseOpenMP.cpp:28
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:32
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.
Preprocessor & getPreprocessor() const
Definition: Parser.h:405
DeclaratorContext
Definition: DeclSpec.h:1733
SmallVector< SourceLocation, OMPMapClause::NumberOfModifiers > MapTypeModifiersLoc
Definition: Parser.h:2944
bool isInvalid() const
Definition: Ownership.h:166
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:708
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:225
Kind
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Definition: Ownership.h:153
ASTContext & getASTContext() const
Definition: Sema.h:1298
Encodes a location in the source.
OpenMPDependClauseKind
OpenMP attributes for &#39;depend&#39; clause.
Definition: OpenMPKinds.h:75
bool is(tok::TokenKind Kind) const
Definition: FormatToken.h:312
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr *> &Vars, OpenMPVarListDataTy &Data)
Parses clauses with list.
static unsigned getOpenMPDirectiveKindEx(StringRef S)
Definition: ParseOpenMP.cpp:67
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:179
OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:22
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:50
Scope * getCurScope() const
Definition: Parser.h:410
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
StringRef getName() const
Return the actual identifier string.
SourceRange getSourceRange() const LLVM_READONLY
Get the source range that spans this declarator.
Definition: DeclSpec.h:1899
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:2441
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:2933
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:108
CXXScopeSpec ReductionOrMapperIdScopeSpec
Definition: Parser.h:2937
Not an overloaded operator.
Definition: OperatorKinds.h:22
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
QualType getCanonicalTypeInternal() const
Definition: Type.h:2375
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:1369
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str)
const char * getOpenMPDirectiveName(OpenMPDirectiveKind Kind)
Definition: OpenMPKinds.cpp:30
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:448
OpenMPMapClauseKind
OpenMP mapping kind for &#39;map&#39; clause.
Definition: OpenMPKinds.h:91
static DeclarationName parseOpenMPReductionId(Parser &P)
This represents &#39;#pragma omp declare mapper ...&#39; directive.
Definition: DeclOpenMP.h:217
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.
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:169
QualType getType() const
Definition: Decl.h:647
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:248
Directive - Abstract class representing a parsed verify directive.
SourceLocation getBegin() const
VerifyDiagnosticConsumer::Directive Directive
SourceLocation getLocation() const
Definition: DeclBase.h:429
OpenMPMapClauseKind MapType
Definition: Parser.h:2945
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:124
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition: Decl.cpp:1772
Stop skipping at specified token, but don&#39;t skip the token itself.
Definition: Parser.h:1071
SourceLocation getEndLoc() const
Definition: Token.h:153