clang  9.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 ThreadprivateListParserHelper final {
48  SmallVector<Expr *, 4> Identifiers;
49  Parser *P;
50 
51 public:
52  ThreadprivateListParserHelper(Parser *P) : P(P) {}
53  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
54  ExprResult Res =
55  P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
56  if (Res.isUsable())
57  Identifiers.push_back(Res.get());
58  }
59  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
60 };
61 } // namespace
62 
63 // Map token string to extended OMP token kind that are
64 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
65 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
66  auto DKind = getOpenMPDirectiveKind(S);
67  if (DKind != OMPD_unknown)
68  return DKind;
69 
70  return llvm::StringSwitch<unsigned>(S)
71  .Case("cancellation", OMPD_cancellation)
72  .Case("data", OMPD_data)
73  .Case("declare", OMPD_declare)
74  .Case("end", OMPD_end)
75  .Case("enter", OMPD_enter)
76  .Case("exit", OMPD_exit)
77  .Case("point", OMPD_point)
78  .Case("reduction", OMPD_reduction)
79  .Case("update", OMPD_update)
80  .Case("mapper", OMPD_mapper)
81  .Default(OMPD_unknown);
82 }
83 
85  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
86  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
87  // TODO: add other combined directives in topological order.
88  static const unsigned F[][3] = {
89  {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
90  {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
91  {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
92  {OMPD_declare, OMPD_simd, OMPD_declare_simd},
93  {OMPD_declare, OMPD_target, OMPD_declare_target},
94  {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
95  {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
96  {OMPD_distribute_parallel_for, OMPD_simd,
97  OMPD_distribute_parallel_for_simd},
98  {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
99  {OMPD_end, OMPD_declare, OMPD_end_declare},
100  {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
101  {OMPD_target, OMPD_data, OMPD_target_data},
102  {OMPD_target, OMPD_enter, OMPD_target_enter},
103  {OMPD_target, OMPD_exit, OMPD_target_exit},
104  {OMPD_target, OMPD_update, OMPD_target_update},
105  {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
106  {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
107  {OMPD_for, OMPD_simd, OMPD_for_simd},
108  {OMPD_parallel, OMPD_for, OMPD_parallel_for},
109  {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
110  {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
111  {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
112  {OMPD_target, OMPD_parallel, OMPD_target_parallel},
113  {OMPD_target, OMPD_simd, OMPD_target_simd},
114  {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
115  {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
116  {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
117  {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
118  {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
119  {OMPD_teams_distribute_parallel, OMPD_for,
120  OMPD_teams_distribute_parallel_for},
121  {OMPD_teams_distribute_parallel_for, OMPD_simd,
122  OMPD_teams_distribute_parallel_for_simd},
123  {OMPD_target, OMPD_teams, OMPD_target_teams},
124  {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
125  {OMPD_target_teams_distribute, OMPD_parallel,
126  OMPD_target_teams_distribute_parallel},
127  {OMPD_target_teams_distribute, OMPD_simd,
128  OMPD_target_teams_distribute_simd},
129  {OMPD_target_teams_distribute_parallel, OMPD_for,
130  OMPD_target_teams_distribute_parallel_for},
131  {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
132  OMPD_target_teams_distribute_parallel_for_simd}};
133  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
134  Token Tok = P.getCurToken();
135  unsigned DKind =
136  Tok.isAnnotation()
137  ? static_cast<unsigned>(OMPD_unknown)
139  if (DKind == OMPD_unknown)
140  return OMPD_unknown;
141 
142  for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
143  if (DKind != F[I][0])
144  continue;
145 
146  Tok = P.getPreprocessor().LookAhead(0);
147  unsigned SDKind =
148  Tok.isAnnotation()
149  ? static_cast<unsigned>(OMPD_unknown)
151  if (SDKind == OMPD_unknown)
152  continue;
153 
154  if (SDKind == F[I][1]) {
155  P.ConsumeToken();
156  DKind = F[I][2];
157  }
158  }
159  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
160  : OMPD_unknown;
161 }
162 
164  Token Tok = P.getCurToken();
165  Sema &Actions = P.getActions();
167  // Allow to use 'operator' keyword for C++ operators
168  bool WithOperator = false;
169  if (Tok.is(tok::kw_operator)) {
170  P.ConsumeToken();
171  Tok = P.getCurToken();
172  WithOperator = true;
173  }
174  switch (Tok.getKind()) {
175  case tok::plus: // '+'
176  OOK = OO_Plus;
177  break;
178  case tok::minus: // '-'
179  OOK = OO_Minus;
180  break;
181  case tok::star: // '*'
182  OOK = OO_Star;
183  break;
184  case tok::amp: // '&'
185  OOK = OO_Amp;
186  break;
187  case tok::pipe: // '|'
188  OOK = OO_Pipe;
189  break;
190  case tok::caret: // '^'
191  OOK = OO_Caret;
192  break;
193  case tok::ampamp: // '&&'
194  OOK = OO_AmpAmp;
195  break;
196  case tok::pipepipe: // '||'
197  OOK = OO_PipePipe;
198  break;
199  case tok::identifier: // identifier
200  if (!WithOperator)
201  break;
202  LLVM_FALLTHROUGH;
203  default:
204  P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
205  P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
207  return DeclarationName();
208  }
209  P.ConsumeToken();
210  auto &DeclNames = Actions.getASTContext().DeclarationNames;
211  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
212  : DeclNames.getCXXOperatorName(OOK);
213 }
214 
215 /// Parse 'omp declare reduction' construct.
216 ///
217 /// declare-reduction-directive:
218 /// annot_pragma_openmp 'declare' 'reduction'
219 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
220 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
221 /// annot_pragma_openmp_end
222 /// <reduction_id> is either a base language identifier or one of the following
223 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
224 ///
226 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
227  // Parse '('.
228  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
229  if (T.expectAndConsume(diag::err_expected_lparen_after,
230  getOpenMPDirectiveName(OMPD_declare_reduction))) {
231  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
232  return DeclGroupPtrTy();
233  }
234 
236  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
237  return DeclGroupPtrTy();
238 
239  // Consume ':'.
240  bool IsCorrect = !ExpectAndConsume(tok::colon);
241 
242  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
243  return DeclGroupPtrTy();
244 
245  IsCorrect = IsCorrect && !Name.isEmpty();
246 
247  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
248  Diag(Tok.getLocation(), diag::err_expected_type);
249  IsCorrect = false;
250  }
251 
252  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
253  return DeclGroupPtrTy();
254 
256  // Parse list of types until ':' token.
257  do {
258  ColonProtectionRAIIObject ColonRAII(*this);
259  SourceRange Range;
260  TypeResult TR =
261  ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
262  if (TR.isUsable()) {
263  QualType ReductionType =
264  Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
265  if (!ReductionType.isNull()) {
266  ReductionTypes.push_back(
267  std::make_pair(ReductionType, Range.getBegin()));
268  }
269  } else {
270  SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
271  StopBeforeMatch);
272  }
273 
274  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
275  break;
276 
277  // Consume ','.
278  if (ExpectAndConsume(tok::comma)) {
279  IsCorrect = false;
280  if (Tok.is(tok::annot_pragma_openmp_end)) {
281  Diag(Tok.getLocation(), diag::err_expected_type);
282  return DeclGroupPtrTy();
283  }
284  }
285  } while (Tok.isNot(tok::annot_pragma_openmp_end));
286 
287  if (ReductionTypes.empty()) {
288  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
289  return DeclGroupPtrTy();
290  }
291 
292  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
293  return DeclGroupPtrTy();
294 
295  // Consume ':'.
296  if (ExpectAndConsume(tok::colon))
297  IsCorrect = false;
298 
299  if (Tok.is(tok::annot_pragma_openmp_end)) {
300  Diag(Tok.getLocation(), diag::err_expected_expression);
301  return DeclGroupPtrTy();
302  }
303 
304  DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
305  getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
306 
307  // Parse <combiner> expression and then parse initializer if any for each
308  // correct type.
309  unsigned I = 0, E = ReductionTypes.size();
310  for (Decl *D : DRD.get()) {
311  TentativeParsingAction TPA(*this);
312  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
315  // Parse <combiner> expression.
316  Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
317  ExprResult CombinerResult =
318  Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
319  D->getLocation(), /*DiscardedValue*/ false);
320  Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
321 
322  if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
323  Tok.isNot(tok::annot_pragma_openmp_end)) {
324  TPA.Commit();
325  IsCorrect = false;
326  break;
327  }
328  IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
329  ExprResult InitializerResult;
330  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
331  // Parse <initializer> expression.
332  if (Tok.is(tok::identifier) &&
333  Tok.getIdentifierInfo()->isStr("initializer")) {
334  ConsumeToken();
335  } else {
336  Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
337  TPA.Commit();
338  IsCorrect = false;
339  break;
340  }
341  // Parse '('.
342  BalancedDelimiterTracker T(*this, tok::l_paren,
343  tok::annot_pragma_openmp_end);
344  IsCorrect =
345  !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
346  IsCorrect;
347  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
348  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
351  // Parse expression.
352  VarDecl *OmpPrivParm =
353  Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
354  D);
355  // Check if initializer is omp_priv <init_expr> or something else.
356  if (Tok.is(tok::identifier) &&
357  Tok.getIdentifierInfo()->isStr("omp_priv")) {
358  if (Actions.getLangOpts().CPlusPlus) {
359  InitializerResult = Actions.ActOnFinishFullExpr(
360  ParseAssignmentExpression().get(), D->getLocation(),
361  /*DiscardedValue*/ false);
362  } else {
363  ConsumeToken();
364  ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
365  }
366  } else {
367  InitializerResult = Actions.ActOnFinishFullExpr(
368  ParseAssignmentExpression().get(), D->getLocation(),
369  /*DiscardedValue*/ false);
370  }
371  Actions.ActOnOpenMPDeclareReductionInitializerEnd(
372  D, InitializerResult.get(), OmpPrivParm);
373  if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
374  Tok.isNot(tok::annot_pragma_openmp_end)) {
375  TPA.Commit();
376  IsCorrect = false;
377  break;
378  }
379  IsCorrect =
380  !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
381  }
382  }
383 
384  ++I;
385  // Revert parsing if not the last type, otherwise accept it, we're done with
386  // parsing.
387  if (I != E)
388  TPA.Revert();
389  else
390  TPA.Commit();
391  }
392  return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
393  IsCorrect);
394 }
395 
396 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
397  // Parse declarator '=' initializer.
398  // If a '==' or '+=' is found, suggest a fixit to '='.
399  if (isTokenEqualOrEqualTypo()) {
400  ConsumeToken();
401 
402  if (Tok.is(tok::code_completion)) {
403  Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
404  Actions.FinalizeDeclaration(OmpPrivParm);
405  cutOffParsing();
406  return;
407  }
408 
409  ExprResult Init(ParseInitializer());
410 
411  if (Init.isInvalid()) {
412  SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
413  Actions.ActOnInitializerError(OmpPrivParm);
414  } else {
415  Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
416  /*DirectInit=*/false);
417  }
418  } else if (Tok.is(tok::l_paren)) {
419  // Parse C++ direct initializer: '(' expression-list ')'
420  BalancedDelimiterTracker T(*this, tok::l_paren);
421  T.consumeOpen();
422 
423  ExprVector Exprs;
424  CommaLocsTy CommaLocs;
425 
426  SourceLocation LParLoc = T.getOpenLocation();
427  if (ParseExpressionList(
428  Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] {
429  QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
430  getCurScope(),
431  OmpPrivParm->getType()->getCanonicalTypeInternal(),
432  OmpPrivParm->getLocation(), Exprs, LParLoc);
433  CalledSignatureHelp = true;
434  Actions.CodeCompleteExpression(getCurScope(), PreferredType);
435  })) {
436  if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
437  Actions.ProduceConstructorSignatureHelp(
438  getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
439  OmpPrivParm->getLocation(), Exprs, LParLoc);
440  CalledSignatureHelp = true;
441  }
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 
453  ExprResult Initializer =
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);
751  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
752  // Consume the previously pushed token.
753  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
754 
755  FNContextRAII FnContext(*this, Ptr);
756  OMPDeclareSimdDeclAttr::BranchStateTy BS =
757  OMPDeclareSimdDeclAttr::BS_Undefined;
758  ExprResult Simdlen;
759  SmallVector<Expr *, 4> Uniforms;
760  SmallVector<Expr *, 4> Aligneds;
761  SmallVector<Expr *, 4> Alignments;
762  SmallVector<Expr *, 4> Linears;
763  SmallVector<unsigned, 4> LinModifiers;
765  bool IsError =
766  parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
767  Alignments, Linears, LinModifiers, Steps);
768  // Need to check for extra tokens.
769  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
770  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
771  << getOpenMPDirectiveName(OMPD_declare_simd);
772  while (Tok.isNot(tok::annot_pragma_openmp_end))
773  ConsumeAnyToken();
774  }
775  // Skip the last annot_pragma_openmp_end.
776  SourceLocation EndLoc = ConsumeAnnotationToken();
777  if (IsError)
778  return Ptr;
779  return Actions.ActOnOpenMPDeclareSimdDirective(
780  Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
781  LinModifiers, Steps, SourceRange(Loc, EndLoc));
782 }
783 
784 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
785  // OpenMP 4.5 syntax with list of entities.
786  Sema::NamedDeclSetType SameDirectiveDecls;
787  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
788  OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
789  if (Tok.is(tok::identifier)) {
790  IdentifierInfo *II = Tok.getIdentifierInfo();
791  StringRef ClauseName = II->getName();
792  // Parse 'to|link' clauses.
793  if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) {
794  Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName;
795  break;
796  }
797  ConsumeToken();
798  }
799  auto &&Callback = [this, MT, &SameDirectiveDecls](
800  CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
801  Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
802  SameDirectiveDecls);
803  };
804  if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
805  /*AllowScopeSpecifier=*/true))
806  break;
807 
808  // Consume optional ','.
809  if (Tok.is(tok::comma))
810  ConsumeToken();
811  }
812  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
813  ConsumeAnyToken();
814  SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
815  SameDirectiveDecls.end());
816  if (Decls.empty())
817  return DeclGroupPtrTy();
818  return Actions.BuildDeclaratorGroup(Decls);
819 }
820 
821 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
822  SourceLocation DTLoc) {
823  if (DKind != OMPD_end_declare_target) {
824  Diag(Tok, diag::err_expected_end_declare_target);
825  Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
826  return;
827  }
828  ConsumeAnyToken();
829  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
830  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
831  << getOpenMPDirectiveName(OMPD_end_declare_target);
832  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
833  }
834  // Skip the last annot_pragma_openmp_end.
835  ConsumeAnyToken();
836 }
837 
838 /// Parsing of declarative OpenMP directives.
839 ///
840 /// threadprivate-directive:
841 /// annot_pragma_openmp 'threadprivate' simple-variable-list
842 /// annot_pragma_openmp_end
843 ///
844 /// declare-reduction-directive:
845 /// annot_pragma_openmp 'declare' 'reduction' [...]
846 /// annot_pragma_openmp_end
847 ///
848 /// declare-mapper-directive:
849 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
850 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
851 /// annot_pragma_openmp_end
852 ///
853 /// declare-simd-directive:
854 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
855 /// annot_pragma_openmp_end
856 /// <function declaration/definition>
857 ///
858 /// requires directive:
859 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
860 /// annot_pragma_openmp_end
861 ///
862 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
863  AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
864  DeclSpec::TST TagType, Decl *Tag) {
865  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
866  ParenBraceBracketBalancer BalancerRAIIObj(*this);
867 
868  SourceLocation Loc = ConsumeAnnotationToken();
870 
871  switch (DKind) {
872  case OMPD_threadprivate: {
873  ConsumeToken();
874  ThreadprivateListParserHelper Helper(this);
875  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
876  // The last seen token is annot_pragma_openmp_end - need to check for
877  // extra tokens.
878  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
879  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
880  << getOpenMPDirectiveName(OMPD_threadprivate);
881  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
882  }
883  // Skip the last annot_pragma_openmp_end.
884  ConsumeAnnotationToken();
885  return Actions.ActOnOpenMPThreadprivateDirective(Loc,
886  Helper.getIdentifiers());
887  }
888  break;
889  }
890  case OMPD_requires: {
891  SourceLocation StartLoc = ConsumeToken();
894  FirstClauses(OMPC_unknown + 1);
895  if (Tok.is(tok::annot_pragma_openmp_end)) {
896  Diag(Tok, diag::err_omp_expected_clause)
897  << getOpenMPDirectiveName(OMPD_requires);
898  break;
899  }
900  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
901  OpenMPClauseKind CKind = Tok.isAnnotation()
902  ? OMPC_unknown
903  : getOpenMPClauseKind(PP.getSpelling(Tok));
904  Actions.StartOpenMPClause(CKind);
905  OMPClause *Clause =
906  ParseOpenMPClause(OMPD_requires, CKind, !FirstClauses[CKind].getInt());
907  SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, StopBeforeMatch);
908  FirstClauses[CKind].setInt(true);
909  if (Clause != nullptr)
910  Clauses.push_back(Clause);
911  if (Tok.is(tok::annot_pragma_openmp_end)) {
912  Actions.EndOpenMPClause();
913  break;
914  }
915  // Skip ',' if any.
916  if (Tok.is(tok::comma))
917  ConsumeToken();
918  Actions.EndOpenMPClause();
919  }
920  // Consume final annot_pragma_openmp_end
921  if (Clauses.size() == 0) {
922  Diag(Tok, diag::err_omp_expected_clause)
923  << getOpenMPDirectiveName(OMPD_requires);
924  ConsumeAnnotationToken();
925  return nullptr;
926  }
927  ConsumeAnnotationToken();
928  return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
929  }
930  case OMPD_declare_reduction:
931  ConsumeToken();
932  if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
933  // The last seen token is annot_pragma_openmp_end - need to check for
934  // extra tokens.
935  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
936  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
937  << getOpenMPDirectiveName(OMPD_declare_reduction);
938  while (Tok.isNot(tok::annot_pragma_openmp_end))
939  ConsumeAnyToken();
940  }
941  // Skip the last annot_pragma_openmp_end.
942  ConsumeAnnotationToken();
943  return Res;
944  }
945  break;
946  case OMPD_declare_mapper: {
947  ConsumeToken();
948  if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
949  // Skip the last annot_pragma_openmp_end.
950  ConsumeAnnotationToken();
951  return Res;
952  }
953  break;
954  }
955  case OMPD_declare_simd: {
956  // The syntax is:
957  // { #pragma omp declare simd }
958  // <function-declaration-or-definition>
959  //
960  ConsumeToken();
961  CachedTokens Toks;
962  while(Tok.isNot(tok::annot_pragma_openmp_end)) {
963  Toks.push_back(Tok);
964  ConsumeAnyToken();
965  }
966  Toks.push_back(Tok);
967  ConsumeAnyToken();
968 
969  DeclGroupPtrTy Ptr;
970  if (Tok.is(tok::annot_pragma_openmp)) {
971  Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
972  } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
973  // Here we expect to see some function declaration.
974  if (AS == AS_none) {
976  MaybeParseCXX11Attributes(Attrs);
977  ParsingDeclSpec PDS(*this);
978  Ptr = ParseExternalDeclaration(Attrs, &PDS);
979  } else {
980  Ptr =
981  ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
982  }
983  }
984  if (!Ptr) {
985  Diag(Loc, diag::err_omp_decl_in_declare_simd);
986  return DeclGroupPtrTy();
987  }
988  return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
989  }
990  case OMPD_declare_target: {
991  SourceLocation DTLoc = ConsumeAnyToken();
992  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
993  return ParseOMPDeclareTargetClauses();
994  }
995 
996  // Skip the last annot_pragma_openmp_end.
997  ConsumeAnyToken();
998 
999  if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1000  return DeclGroupPtrTy();
1001 
1003  DKind = parseOpenMPDirectiveKind(*this);
1004  while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1005  Tok.isNot(tok::r_brace)) {
1006  DeclGroupPtrTy Ptr;
1007  // Here we expect to see some function declaration.
1008  if (AS == AS_none) {
1010  MaybeParseCXX11Attributes(Attrs);
1011  ParsingDeclSpec PDS(*this);
1012  Ptr = ParseExternalDeclaration(Attrs, &PDS);
1013  } else {
1014  Ptr =
1015  ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1016  }
1017  if (Ptr) {
1018  DeclGroupRef Ref = Ptr.get();
1019  Decls.append(Ref.begin(), Ref.end());
1020  }
1021  if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
1022  TentativeParsingAction TPA(*this);
1023  ConsumeAnnotationToken();
1024  DKind = parseOpenMPDirectiveKind(*this);
1025  if (DKind != OMPD_end_declare_target)
1026  TPA.Revert();
1027  else
1028  TPA.Commit();
1029  }
1030  }
1031 
1032  ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1033  Actions.ActOnFinishOpenMPDeclareTargetDirective();
1034  return Actions.BuildDeclaratorGroup(Decls);
1035  }
1036  case OMPD_unknown:
1037  Diag(Tok, diag::err_omp_unknown_directive);
1038  break;
1039  case OMPD_parallel:
1040  case OMPD_simd:
1041  case OMPD_task:
1042  case OMPD_taskyield:
1043  case OMPD_barrier:
1044  case OMPD_taskwait:
1045  case OMPD_taskgroup:
1046  case OMPD_flush:
1047  case OMPD_for:
1048  case OMPD_for_simd:
1049  case OMPD_sections:
1050  case OMPD_section:
1051  case OMPD_single:
1052  case OMPD_master:
1053  case OMPD_ordered:
1054  case OMPD_critical:
1055  case OMPD_parallel_for:
1056  case OMPD_parallel_for_simd:
1057  case OMPD_parallel_sections:
1058  case OMPD_atomic:
1059  case OMPD_target:
1060  case OMPD_teams:
1061  case OMPD_cancellation_point:
1062  case OMPD_cancel:
1063  case OMPD_target_data:
1064  case OMPD_target_enter_data:
1065  case OMPD_target_exit_data:
1066  case OMPD_target_parallel:
1067  case OMPD_target_parallel_for:
1068  case OMPD_taskloop:
1069  case OMPD_taskloop_simd:
1070  case OMPD_distribute:
1071  case OMPD_end_declare_target:
1072  case OMPD_target_update:
1073  case OMPD_distribute_parallel_for:
1074  case OMPD_distribute_parallel_for_simd:
1075  case OMPD_distribute_simd:
1076  case OMPD_target_parallel_for_simd:
1077  case OMPD_target_simd:
1078  case OMPD_teams_distribute:
1079  case OMPD_teams_distribute_simd:
1080  case OMPD_teams_distribute_parallel_for_simd:
1081  case OMPD_teams_distribute_parallel_for:
1082  case OMPD_target_teams:
1083  case OMPD_target_teams_distribute:
1084  case OMPD_target_teams_distribute_parallel_for:
1085  case OMPD_target_teams_distribute_parallel_for_simd:
1086  case OMPD_target_teams_distribute_simd:
1087  Diag(Tok, diag::err_omp_unexpected_directive)
1088  << 1 << getOpenMPDirectiveName(DKind);
1089  break;
1090  }
1091  while (Tok.isNot(tok::annot_pragma_openmp_end))
1092  ConsumeAnyToken();
1093  ConsumeAnyToken();
1094  return nullptr;
1095 }
1096 
1097 /// Parsing of declarative or executable OpenMP directives.
1098 ///
1099 /// threadprivate-directive:
1100 /// annot_pragma_openmp 'threadprivate' simple-variable-list
1101 /// annot_pragma_openmp_end
1102 ///
1103 /// declare-reduction-directive:
1104 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
1105 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
1106 /// ('omp_priv' '=' <expression>|<function_call>) ')']
1107 /// annot_pragma_openmp_end
1108 ///
1109 /// declare-mapper-directive:
1110 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1111 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
1112 /// annot_pragma_openmp_end
1113 ///
1114 /// executable-directive:
1115 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
1116 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
1117 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
1118 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
1119 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
1120 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
1121 /// 'distribute' | 'target enter data' | 'target exit data' |
1122 /// 'target parallel' | 'target parallel for' |
1123 /// 'target update' | 'distribute parallel for' |
1124 /// 'distribute paralle for simd' | 'distribute simd' |
1125 /// 'target parallel for simd' | 'target simd' |
1126 /// 'teams distribute' | 'teams distribute simd' |
1127 /// 'teams distribute parallel for simd' |
1128 /// 'teams distribute parallel for' | 'target teams' |
1129 /// 'target teams distribute' |
1130 /// 'target teams distribute parallel for' |
1131 /// 'target teams distribute parallel for simd' |
1132 /// 'target teams distribute simd' {clause}
1133 /// annot_pragma_openmp_end
1134 ///
1135 StmtResult
1136 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1137  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1138  ParenBraceBracketBalancer BalancerRAIIObj(*this);
1141  FirstClauses(OMPC_unknown + 1);
1142  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
1144  SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
1146  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
1147  // Name of critical directive.
1148  DeclarationNameInfo DirName;
1150  bool HasAssociatedStatement = true;
1151  bool FlushHasClause = false;
1152 
1153  switch (DKind) {
1154  case OMPD_threadprivate: {
1155  // FIXME: Should this be permitted in C++?
1156  if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1157  ParsedStmtContext()) {
1158  Diag(Tok, diag::err_omp_immediate_directive)
1159  << getOpenMPDirectiveName(DKind) << 0;
1160  }
1161  ConsumeToken();
1162  ThreadprivateListParserHelper Helper(this);
1163  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
1164  // The last seen token is annot_pragma_openmp_end - need to check for
1165  // extra tokens.
1166  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1167  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1168  << getOpenMPDirectiveName(OMPD_threadprivate);
1169  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1170  }
1171  DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
1172  Loc, Helper.getIdentifiers());
1173  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1174  }
1175  SkipUntil(tok::annot_pragma_openmp_end);
1176  break;
1177  }
1178  case OMPD_declare_reduction:
1179  ConsumeToken();
1180  if (DeclGroupPtrTy Res =
1181  ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
1182  // The last seen token is annot_pragma_openmp_end - need to check for
1183  // extra tokens.
1184  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1185  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1186  << getOpenMPDirectiveName(OMPD_declare_reduction);
1187  while (Tok.isNot(tok::annot_pragma_openmp_end))
1188  ConsumeAnyToken();
1189  }
1190  ConsumeAnyToken();
1191  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1192  } else {
1193  SkipUntil(tok::annot_pragma_openmp_end);
1194  }
1195  break;
1196  case OMPD_declare_mapper: {
1197  ConsumeToken();
1198  if (DeclGroupPtrTy Res =
1199  ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
1200  // Skip the last annot_pragma_openmp_end.
1201  ConsumeAnnotationToken();
1202  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1203  } else {
1204  SkipUntil(tok::annot_pragma_openmp_end);
1205  }
1206  break;
1207  }
1208  case OMPD_flush:
1209  if (PP.LookAhead(0).is(tok::l_paren)) {
1210  FlushHasClause = true;
1211  // Push copy of the current token back to stream to properly parse
1212  // pseudo-clause OMPFlushClause.
1213  PP.EnterToken(Tok);
1214  }
1215  LLVM_FALLTHROUGH;
1216  case OMPD_taskyield:
1217  case OMPD_barrier:
1218  case OMPD_taskwait:
1219  case OMPD_cancellation_point:
1220  case OMPD_cancel:
1221  case OMPD_target_enter_data:
1222  case OMPD_target_exit_data:
1223  case OMPD_target_update:
1224  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1225  ParsedStmtContext()) {
1226  Diag(Tok, diag::err_omp_immediate_directive)
1227  << getOpenMPDirectiveName(DKind) << 0;
1228  }
1229  HasAssociatedStatement = false;
1230  // Fall through for further analysis.
1231  LLVM_FALLTHROUGH;
1232  case OMPD_parallel:
1233  case OMPD_simd:
1234  case OMPD_for:
1235  case OMPD_for_simd:
1236  case OMPD_sections:
1237  case OMPD_single:
1238  case OMPD_section:
1239  case OMPD_master:
1240  case OMPD_critical:
1241  case OMPD_parallel_for:
1242  case OMPD_parallel_for_simd:
1243  case OMPD_parallel_sections:
1244  case OMPD_task:
1245  case OMPD_ordered:
1246  case OMPD_atomic:
1247  case OMPD_target:
1248  case OMPD_teams:
1249  case OMPD_taskgroup:
1250  case OMPD_target_data:
1251  case OMPD_target_parallel:
1252  case OMPD_target_parallel_for:
1253  case OMPD_taskloop:
1254  case OMPD_taskloop_simd:
1255  case OMPD_distribute:
1256  case OMPD_distribute_parallel_for:
1257  case OMPD_distribute_parallel_for_simd:
1258  case OMPD_distribute_simd:
1259  case OMPD_target_parallel_for_simd:
1260  case OMPD_target_simd:
1261  case OMPD_teams_distribute:
1262  case OMPD_teams_distribute_simd:
1263  case OMPD_teams_distribute_parallel_for_simd:
1264  case OMPD_teams_distribute_parallel_for:
1265  case OMPD_target_teams:
1266  case OMPD_target_teams_distribute:
1267  case OMPD_target_teams_distribute_parallel_for:
1268  case OMPD_target_teams_distribute_parallel_for_simd:
1269  case OMPD_target_teams_distribute_simd: {
1270  ConsumeToken();
1271  // Parse directive name of the 'critical' directive if any.
1272  if (DKind == OMPD_critical) {
1273  BalancedDelimiterTracker T(*this, tok::l_paren,
1274  tok::annot_pragma_openmp_end);
1275  if (!T.consumeOpen()) {
1276  if (Tok.isAnyIdentifier()) {
1277  DirName =
1278  DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1279  ConsumeAnyToken();
1280  } else {
1281  Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1282  }
1283  T.consumeClose();
1284  }
1285  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1286  CancelRegion = parseOpenMPDirectiveKind(*this);
1287  if (Tok.isNot(tok::annot_pragma_openmp_end))
1288  ConsumeToken();
1289  }
1290 
1291  if (isOpenMPLoopDirective(DKind))
1292  ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1293  if (isOpenMPSimdDirective(DKind))
1294  ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1295  ParseScope OMPDirectiveScope(this, ScopeFlags);
1296  Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1297 
1298  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1299  OpenMPClauseKind CKind =
1300  Tok.isAnnotation()
1301  ? OMPC_unknown
1302  : FlushHasClause ? OMPC_flush
1303  : getOpenMPClauseKind(PP.getSpelling(Tok));
1304  Actions.StartOpenMPClause(CKind);
1305  FlushHasClause = false;
1306  OMPClause *Clause =
1307  ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1308  FirstClauses[CKind].setInt(true);
1309  if (Clause) {
1310  FirstClauses[CKind].setPointer(Clause);
1311  Clauses.push_back(Clause);
1312  }
1313 
1314  // Skip ',' if any.
1315  if (Tok.is(tok::comma))
1316  ConsumeToken();
1317  Actions.EndOpenMPClause();
1318  }
1319  // End location of the directive.
1320  EndLoc = Tok.getLocation();
1321  // Consume final annot_pragma_openmp_end.
1322  ConsumeAnnotationToken();
1323 
1324  // OpenMP [2.13.8, ordered Construct, Syntax]
1325  // If the depend clause is specified, the ordered construct is a stand-alone
1326  // directive.
1327  if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1328  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1329  ParsedStmtContext()) {
1330  Diag(Loc, diag::err_omp_immediate_directive)
1331  << getOpenMPDirectiveName(DKind) << 1
1332  << getOpenMPClauseName(OMPC_depend);
1333  }
1334  HasAssociatedStatement = false;
1335  }
1336 
1337  StmtResult AssociatedStmt;
1338  if (HasAssociatedStatement) {
1339  // The body is a block scope like in Lambdas and Blocks.
1340  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1341  // FIXME: We create a bogus CompoundStmt scope to hold the contents of
1342  // the captured region. Code elsewhere assumes that any FunctionScopeInfo
1343  // should have at least one compound statement scope within it.
1344  AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
1345  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1346  } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1347  DKind == OMPD_target_exit_data) {
1348  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1349  AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
1350  Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
1351  /*isStmtExpr=*/false));
1352  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1353  }
1354  Directive = Actions.ActOnOpenMPExecutableDirective(
1355  DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1356  EndLoc);
1357 
1358  // Exit scope.
1359  Actions.EndOpenMPDSABlock(Directive.get());
1360  OMPDirectiveScope.Exit();
1361  break;
1362  }
1363  case OMPD_declare_simd:
1364  case OMPD_declare_target:
1365  case OMPD_end_declare_target:
1366  case OMPD_requires:
1367  Diag(Tok, diag::err_omp_unexpected_directive)
1368  << 1 << getOpenMPDirectiveName(DKind);
1369  SkipUntil(tok::annot_pragma_openmp_end);
1370  break;
1371  case OMPD_unknown:
1372  Diag(Tok, diag::err_omp_unknown_directive);
1373  SkipUntil(tok::annot_pragma_openmp_end);
1374  break;
1375  }
1376  return Directive;
1377 }
1378 
1379 // Parses simple list:
1380 // simple-variable-list:
1381 // '(' id-expression {, id-expression} ')'
1382 //
1383 bool Parser::ParseOpenMPSimpleVarList(
1385  const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1386  Callback,
1387  bool AllowScopeSpecifier) {
1388  // Parse '('.
1389  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1390  if (T.expectAndConsume(diag::err_expected_lparen_after,
1392  return true;
1393  bool IsCorrect = true;
1394  bool NoIdentIsFound = true;
1395 
1396  // Read tokens while ')' or annot_pragma_openmp_end is not found.
1397  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1398  CXXScopeSpec SS;
1399  UnqualifiedId Name;
1400  // Read var name.
1401  Token PrevTok = Tok;
1402  NoIdentIsFound = false;
1403 
1404  if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1405  ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1406  IsCorrect = false;
1407  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1408  StopBeforeMatch);
1409  } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1410  nullptr, Name)) {
1411  IsCorrect = false;
1412  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1413  StopBeforeMatch);
1414  } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1415  Tok.isNot(tok::annot_pragma_openmp_end)) {
1416  IsCorrect = false;
1417  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1418  StopBeforeMatch);
1419  Diag(PrevTok.getLocation(), diag::err_expected)
1420  << tok::identifier
1421  << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1422  } else {
1423  Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1424  }
1425  // Consume ','.
1426  if (Tok.is(tok::comma)) {
1427  ConsumeToken();
1428  }
1429  }
1430 
1431  if (NoIdentIsFound) {
1432  Diag(Tok, diag::err_expected) << tok::identifier;
1433  IsCorrect = false;
1434  }
1435 
1436  // Parse ')'.
1437  IsCorrect = !T.consumeClose() && IsCorrect;
1438 
1439  return !IsCorrect;
1440 }
1441 
1442 /// Parsing of OpenMP clauses.
1443 ///
1444 /// clause:
1445 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1446 /// default-clause | private-clause | firstprivate-clause | shared-clause
1447 /// | linear-clause | aligned-clause | collapse-clause |
1448 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1449 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1450 /// mergeable-clause | flush-clause | read-clause | write-clause |
1451 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1452 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1453 /// thread_limit-clause | priority-clause | grainsize-clause |
1454 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1455 /// from-clause | is_device_ptr-clause | task_reduction-clause |
1456 /// in_reduction-clause
1457 ///
1458 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1459  OpenMPClauseKind CKind, bool FirstClause) {
1460  OMPClause *Clause = nullptr;
1461  bool ErrorFound = false;
1462  bool WrongDirective = false;
1463  // Check if clause is allowed for the given directive.
1464  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1465  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1466  << getOpenMPDirectiveName(DKind);
1467  ErrorFound = true;
1468  WrongDirective = true;
1469  }
1470 
1471  switch (CKind) {
1472  case OMPC_final:
1473  case OMPC_num_threads:
1474  case OMPC_safelen:
1475  case OMPC_simdlen:
1476  case OMPC_collapse:
1477  case OMPC_ordered:
1478  case OMPC_device:
1479  case OMPC_num_teams:
1480  case OMPC_thread_limit:
1481  case OMPC_priority:
1482  case OMPC_grainsize:
1483  case OMPC_num_tasks:
1484  case OMPC_hint:
1485  // OpenMP [2.5, Restrictions]
1486  // At most one num_threads clause can appear on the directive.
1487  // OpenMP [2.8.1, simd construct, Restrictions]
1488  // Only one safelen clause can appear on a simd directive.
1489  // Only one simdlen clause can appear on a simd directive.
1490  // Only one collapse clause can appear on a simd directive.
1491  // OpenMP [2.9.1, target data construct, Restrictions]
1492  // At most one device clause can appear on the directive.
1493  // OpenMP [2.11.1, task Construct, Restrictions]
1494  // At most one if clause can appear on the directive.
1495  // At most one final clause can appear on the directive.
1496  // OpenMP [teams Construct, Restrictions]
1497  // At most one num_teams clause can appear on the directive.
1498  // At most one thread_limit clause can appear on the directive.
1499  // OpenMP [2.9.1, task Construct, Restrictions]
1500  // At most one priority clause can appear on the directive.
1501  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1502  // At most one grainsize clause can appear on the directive.
1503  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1504  // At most one num_tasks clause can appear on the directive.
1505  if (!FirstClause) {
1506  Diag(Tok, diag::err_omp_more_one_clause)
1507  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1508  ErrorFound = true;
1509  }
1510 
1511  if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1512  Clause = ParseOpenMPClause(CKind, WrongDirective);
1513  else
1514  Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
1515  break;
1516  case OMPC_default:
1517  case OMPC_proc_bind:
1518  case OMPC_atomic_default_mem_order:
1519  // OpenMP [2.14.3.1, Restrictions]
1520  // Only a single default clause may be specified on a parallel, task or
1521  // teams directive.
1522  // OpenMP [2.5, parallel Construct, Restrictions]
1523  // At most one proc_bind clause can appear on the directive.
1524  // OpenMP [5.0, Requires directive, Restrictions]
1525  // At most one atomic_default_mem_order clause can appear
1526  // on the directive
1527  if (!FirstClause) {
1528  Diag(Tok, diag::err_omp_more_one_clause)
1529  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1530  ErrorFound = true;
1531  }
1532 
1533  Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
1534  break;
1535  case OMPC_schedule:
1536  case OMPC_dist_schedule:
1537  case OMPC_defaultmap:
1538  // OpenMP [2.7.1, Restrictions, p. 3]
1539  // Only one schedule clause can appear on a loop directive.
1540  // OpenMP [2.10.4, Restrictions, p. 106]
1541  // At most one defaultmap clause can appear on the directive.
1542  if (!FirstClause) {
1543  Diag(Tok, diag::err_omp_more_one_clause)
1544  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1545  ErrorFound = true;
1546  }
1547  LLVM_FALLTHROUGH;
1548 
1549  case OMPC_if:
1550  Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
1551  break;
1552  case OMPC_nowait:
1553  case OMPC_untied:
1554  case OMPC_mergeable:
1555  case OMPC_read:
1556  case OMPC_write:
1557  case OMPC_update:
1558  case OMPC_capture:
1559  case OMPC_seq_cst:
1560  case OMPC_threads:
1561  case OMPC_simd:
1562  case OMPC_nogroup:
1563  case OMPC_unified_address:
1564  case OMPC_unified_shared_memory:
1565  case OMPC_reverse_offload:
1566  case OMPC_dynamic_allocators:
1567  // OpenMP [2.7.1, Restrictions, p. 9]
1568  // Only one ordered clause can appear on a loop directive.
1569  // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1570  // Only one nowait clause can appear on a for directive.
1571  // OpenMP [5.0, Requires directive, Restrictions]
1572  // Each of the requires clauses can appear at most once on the directive.
1573  if (!FirstClause) {
1574  Diag(Tok, diag::err_omp_more_one_clause)
1575  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1576  ErrorFound = true;
1577  }
1578 
1579  Clause = ParseOpenMPClause(CKind, WrongDirective);
1580  break;
1581  case OMPC_private:
1582  case OMPC_firstprivate:
1583  case OMPC_lastprivate:
1584  case OMPC_shared:
1585  case OMPC_reduction:
1586  case OMPC_task_reduction:
1587  case OMPC_in_reduction:
1588  case OMPC_linear:
1589  case OMPC_aligned:
1590  case OMPC_copyin:
1591  case OMPC_copyprivate:
1592  case OMPC_flush:
1593  case OMPC_depend:
1594  case OMPC_map:
1595  case OMPC_to:
1596  case OMPC_from:
1597  case OMPC_use_device_ptr:
1598  case OMPC_is_device_ptr:
1599  Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
1600  break;
1601  case OMPC_unknown:
1602  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1603  << getOpenMPDirectiveName(DKind);
1604  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1605  break;
1606  case OMPC_threadprivate:
1607  case OMPC_uniform:
1608  if (!WrongDirective)
1609  Diag(Tok, diag::err_omp_unexpected_clause)
1610  << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
1611  SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1612  break;
1613  }
1614  return ErrorFound ? nullptr : Clause;
1615 }
1616 
1617 /// Parses simple expression in parens for single-expression clauses of OpenMP
1618 /// constructs.
1619 /// \param RLoc Returned location of right paren.
1621  SourceLocation &RLoc) {
1622  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1623  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1624  return ExprError();
1625 
1626  SourceLocation ELoc = Tok.getLocation();
1627  ExprResult LHS(ParseCastExpression(
1628  /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1629  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1630  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
1631 
1632  // Parse ')'.
1633  RLoc = Tok.getLocation();
1634  if (!T.consumeClose())
1635  RLoc = T.getCloseLocation();
1636 
1637  return Val;
1638 }
1639 
1640 /// Parsing of OpenMP clauses with single expressions like 'final',
1641 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1642 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1643 ///
1644 /// final-clause:
1645 /// 'final' '(' expression ')'
1646 ///
1647 /// num_threads-clause:
1648 /// 'num_threads' '(' expression ')'
1649 ///
1650 /// safelen-clause:
1651 /// 'safelen' '(' expression ')'
1652 ///
1653 /// simdlen-clause:
1654 /// 'simdlen' '(' expression ')'
1655 ///
1656 /// collapse-clause:
1657 /// 'collapse' '(' expression ')'
1658 ///
1659 /// priority-clause:
1660 /// 'priority' '(' expression ')'
1661 ///
1662 /// grainsize-clause:
1663 /// 'grainsize' '(' expression ')'
1664 ///
1665 /// num_tasks-clause:
1666 /// 'num_tasks' '(' expression ')'
1667 ///
1668 /// hint-clause:
1669 /// 'hint' '(' expression ')'
1670 ///
1671 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
1672  bool ParseOnly) {
1673  SourceLocation Loc = ConsumeToken();
1674  SourceLocation LLoc = Tok.getLocation();
1675  SourceLocation RLoc;
1676 
1677  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1678 
1679  if (Val.isInvalid())
1680  return nullptr;
1681 
1682  if (ParseOnly)
1683  return nullptr;
1684  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1685 }
1686 
1687 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1688 ///
1689 /// default-clause:
1690 /// 'default' '(' 'none' | 'shared' ')
1691 ///
1692 /// proc_bind-clause:
1693 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1694 ///
1695 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
1696  bool ParseOnly) {
1697  SourceLocation Loc = Tok.getLocation();
1698  SourceLocation LOpen = ConsumeToken();
1699  // Parse '('.
1700  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1701  if (T.expectAndConsume(diag::err_expected_lparen_after,
1703  return nullptr;
1704 
1705  unsigned Type = getOpenMPSimpleClauseType(
1706  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1707  SourceLocation TypeLoc = Tok.getLocation();
1708  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1709  Tok.isNot(tok::annot_pragma_openmp_end))
1710  ConsumeAnyToken();
1711 
1712  // Parse ')'.
1713  SourceLocation RLoc = Tok.getLocation();
1714  if (!T.consumeClose())
1715  RLoc = T.getCloseLocation();
1716 
1717  if (ParseOnly)
1718  return nullptr;
1719  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
1720 }
1721 
1722 /// Parsing of OpenMP clauses like 'ordered'.
1723 ///
1724 /// ordered-clause:
1725 /// 'ordered'
1726 ///
1727 /// nowait-clause:
1728 /// 'nowait'
1729 ///
1730 /// untied-clause:
1731 /// 'untied'
1732 ///
1733 /// mergeable-clause:
1734 /// 'mergeable'
1735 ///
1736 /// read-clause:
1737 /// 'read'
1738 ///
1739 /// threads-clause:
1740 /// 'threads'
1741 ///
1742 /// simd-clause:
1743 /// 'simd'
1744 ///
1745 /// nogroup-clause:
1746 /// 'nogroup'
1747 ///
1748 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
1749  SourceLocation Loc = Tok.getLocation();
1750  ConsumeAnyToken();
1751 
1752  if (ParseOnly)
1753  return nullptr;
1754  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1755 }
1756 
1757 
1758 /// Parsing of OpenMP clauses with single expressions and some additional
1759 /// argument like 'schedule' or 'dist_schedule'.
1760 ///
1761 /// schedule-clause:
1762 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1763 /// ')'
1764 ///
1765 /// if-clause:
1766 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1767 ///
1768 /// defaultmap:
1769 /// 'defaultmap' '(' modifier ':' kind ')'
1770 ///
1771 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
1772  bool ParseOnly) {
1773  SourceLocation Loc = ConsumeToken();
1774  SourceLocation DelimLoc;
1775  // Parse '('.
1776  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1777  if (T.expectAndConsume(diag::err_expected_lparen_after,
1779  return nullptr;
1780 
1781  ExprResult Val;
1784  if (Kind == OMPC_schedule) {
1785  enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1786  Arg.resize(NumberOfElements);
1787  KLoc.resize(NumberOfElements);
1788  Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1789  Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1790  Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1791  unsigned KindModifier = getOpenMPSimpleClauseType(
1792  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1793  if (KindModifier > OMPC_SCHEDULE_unknown) {
1794  // Parse 'modifier'
1795  Arg[Modifier1] = KindModifier;
1796  KLoc[Modifier1] = Tok.getLocation();
1797  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1798  Tok.isNot(tok::annot_pragma_openmp_end))
1799  ConsumeAnyToken();
1800  if (Tok.is(tok::comma)) {
1801  // Parse ',' 'modifier'
1802  ConsumeAnyToken();
1803  KindModifier = getOpenMPSimpleClauseType(
1804  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1805  Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1806  ? KindModifier
1807  : (unsigned)OMPC_SCHEDULE_unknown;
1808  KLoc[Modifier2] = Tok.getLocation();
1809  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1810  Tok.isNot(tok::annot_pragma_openmp_end))
1811  ConsumeAnyToken();
1812  }
1813  // Parse ':'
1814  if (Tok.is(tok::colon))
1815  ConsumeAnyToken();
1816  else
1817  Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1818  KindModifier = getOpenMPSimpleClauseType(
1819  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1820  }
1821  Arg[ScheduleKind] = KindModifier;
1822  KLoc[ScheduleKind] = Tok.getLocation();
1823  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1824  Tok.isNot(tok::annot_pragma_openmp_end))
1825  ConsumeAnyToken();
1826  if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1827  Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1828  Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1829  Tok.is(tok::comma))
1830  DelimLoc = ConsumeAnyToken();
1831  } else if (Kind == OMPC_dist_schedule) {
1832  Arg.push_back(getOpenMPSimpleClauseType(
1833  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1834  KLoc.push_back(Tok.getLocation());
1835  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1836  Tok.isNot(tok::annot_pragma_openmp_end))
1837  ConsumeAnyToken();
1838  if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1839  DelimLoc = ConsumeAnyToken();
1840  } else if (Kind == OMPC_defaultmap) {
1841  // Get a defaultmap modifier
1842  Arg.push_back(getOpenMPSimpleClauseType(
1843  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1844  KLoc.push_back(Tok.getLocation());
1845  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1846  Tok.isNot(tok::annot_pragma_openmp_end))
1847  ConsumeAnyToken();
1848  // Parse ':'
1849  if (Tok.is(tok::colon))
1850  ConsumeAnyToken();
1851  else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1852  Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1853  // Get a defaultmap kind
1854  Arg.push_back(getOpenMPSimpleClauseType(
1855  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1856  KLoc.push_back(Tok.getLocation());
1857  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1858  Tok.isNot(tok::annot_pragma_openmp_end))
1859  ConsumeAnyToken();
1860  } else {
1861  assert(Kind == OMPC_if);
1862  KLoc.push_back(Tok.getLocation());
1863  TentativeParsingAction TPA(*this);
1864  Arg.push_back(parseOpenMPDirectiveKind(*this));
1865  if (Arg.back() != OMPD_unknown) {
1866  ConsumeToken();
1867  if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1868  TPA.Commit();
1869  DelimLoc = ConsumeToken();
1870  } else {
1871  TPA.Revert();
1872  Arg.back() = OMPD_unknown;
1873  }
1874  } else {
1875  TPA.Revert();
1876  }
1877  }
1878 
1879  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1880  (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1881  Kind == OMPC_if;
1882  if (NeedAnExpression) {
1883  SourceLocation ELoc = Tok.getLocation();
1884  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
1885  Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
1886  Val =
1887  Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
1888  }
1889 
1890  // Parse ')'.
1891  SourceLocation RLoc = Tok.getLocation();
1892  if (!T.consumeClose())
1893  RLoc = T.getCloseLocation();
1894 
1895  if (NeedAnExpression && Val.isInvalid())
1896  return nullptr;
1897 
1898  if (ParseOnly)
1899  return nullptr;
1900  return Actions.ActOnOpenMPSingleExprWithArgClause(
1901  Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
1902 }
1903 
1904 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
1905  UnqualifiedId &ReductionId) {
1906  if (ReductionIdScopeSpec.isEmpty()) {
1907  auto OOK = OO_None;
1908  switch (P.getCurToken().getKind()) {
1909  case tok::plus:
1910  OOK = OO_Plus;
1911  break;
1912  case tok::minus:
1913  OOK = OO_Minus;
1914  break;
1915  case tok::star:
1916  OOK = OO_Star;
1917  break;
1918  case tok::amp:
1919  OOK = OO_Amp;
1920  break;
1921  case tok::pipe:
1922  OOK = OO_Pipe;
1923  break;
1924  case tok::caret:
1925  OOK = OO_Caret;
1926  break;
1927  case tok::ampamp:
1928  OOK = OO_AmpAmp;
1929  break;
1930  case tok::pipepipe:
1931  OOK = OO_PipePipe;
1932  break;
1933  default:
1934  break;
1935  }
1936  if (OOK != OO_None) {
1937  SourceLocation OpLoc = P.ConsumeToken();
1938  SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
1939  ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
1940  return false;
1941  }
1942  }
1943  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
1944  /*AllowDestructorName*/ false,
1945  /*AllowConstructorName*/ false,
1946  /*AllowDeductionGuide*/ false,
1947  nullptr, nullptr, ReductionId);
1948 }
1949 
1950 /// Checks if the token is a valid map-type-modifier.
1952  Token Tok = P.getCurToken();
1953  if (!Tok.is(tok::identifier))
1955 
1956  Preprocessor &PP = P.getPreprocessor();
1957  OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
1958  getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
1959  return TypeModifier;
1960 }
1961 
1962 /// Parse map-type-modifiers in map clause.
1963 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
1964 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
1966  while (getCurToken().isNot(tok::colon)) {
1967  OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
1968  if (TypeModifier == OMPC_MAP_MODIFIER_always ||
1969  TypeModifier == OMPC_MAP_MODIFIER_close) {
1970  Data.MapTypeModifiers.push_back(TypeModifier);
1971  Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
1972  ConsumeToken();
1973  } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
1974  Data.MapTypeModifiers.push_back(TypeModifier);
1975  Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
1976  ConsumeToken();
1977  // Parse '('.
1978  BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
1979  if (T.expectAndConsume(diag::err_expected_lparen_after,
1981  OMPC_map, OMPC_MAP_MODIFIER_mapper))) {
1982  SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
1983  return true;
1984  }
1985  // Parse mapper-identifier
1986  if (getLangOpts().CPlusPlus)
1987  ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
1988  /*ObjectType=*/nullptr,
1989  /*EnteringContext=*/false);
1990  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
1991  Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
1992  SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
1993  return true;
1994  }
1995  auto &DeclNames = Actions.getASTContext().DeclarationNames;
1997  DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
1998  ConsumeToken();
1999  // Parse ')'.
2000  T.consumeClose();
2001  } else {
2002  // For the case of unknown map-type-modifier or a map-type.
2003  // Map-type is followed by a colon; the function returns when it
2004  // encounters a token followed by a colon.
2005  if (Tok.is(tok::comma)) {
2006  Diag(Tok, diag::err_omp_map_type_modifier_missing);
2007  ConsumeToken();
2008  continue;
2009  }
2010  // Potential map-type token as it is followed by a colon.
2011  if (PP.LookAhead(0).is(tok::colon))
2012  return false;
2013  Diag(Tok, diag::err_omp_unknown_map_type_modifier);
2014  ConsumeToken();
2015  }
2016  if (getCurToken().is(tok::comma))
2017  ConsumeToken();
2018  }
2019  return false;
2020 }
2021 
2022 /// Checks if the token is a valid map-type.
2024  Token Tok = P.getCurToken();
2025  // The map-type token can be either an identifier or the C++ delete keyword.
2026  if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
2027  return OMPC_MAP_unknown;
2028  Preprocessor &PP = P.getPreprocessor();
2029  OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
2030  getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2031  return MapType;
2032 }
2033 
2034 /// Parse map-type in map clause.
2035 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2036 /// where, map-type ::= to | from | tofrom | alloc | release | delete
2038  Token Tok = P.getCurToken();
2039  if (Tok.is(tok::colon)) {
2040  P.Diag(Tok, diag::err_omp_map_type_missing);
2041  return;
2042  }
2043  Data.MapType = isMapType(P);
2044  if (Data.MapType == OMPC_MAP_unknown)
2045  P.Diag(Tok, diag::err_omp_unknown_map_type);
2046  P.ConsumeToken();
2047 }
2048 
2049 /// Parses clauses with list.
2053  OpenMPVarListDataTy &Data) {
2054  UnqualifiedId UnqualifiedReductionId;
2055  bool InvalidReductionId = false;
2056  bool IsInvalidMapModifier = false;
2057 
2058  // Parse '('.
2059  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2060  if (T.expectAndConsume(diag::err_expected_lparen_after,
2061  getOpenMPClauseName(Kind)))
2062  return true;
2063 
2064  bool NeedRParenForLinear = false;
2065  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
2066  tok::annot_pragma_openmp_end);
2067  // Handle reduction-identifier for reduction clause.
2068  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
2069  Kind == OMPC_in_reduction) {
2070  ColonProtectionRAIIObject ColonRAII(*this);
2071  if (getLangOpts().CPlusPlus)
2072  ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2073  /*ObjectType=*/nullptr,
2074  /*EnteringContext=*/false);
2075  InvalidReductionId = ParseReductionId(
2076  *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
2077  if (InvalidReductionId) {
2078  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2079  StopBeforeMatch);
2080  }
2081  if (Tok.is(tok::colon))
2082  Data.ColonLoc = ConsumeToken();
2083  else
2084  Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
2085  if (!InvalidReductionId)
2086  Data.ReductionOrMapperId =
2087  Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
2088  } else if (Kind == OMPC_depend) {
2089  // Handle dependency type for depend clause.
2090  ColonProtectionRAIIObject ColonRAII(*this);
2091  Data.DepKind =
2093  Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
2094  Data.DepLinMapLoc = Tok.getLocation();
2095 
2096  if (Data.DepKind == OMPC_DEPEND_unknown) {
2097  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2098  StopBeforeMatch);
2099  } else {
2100  ConsumeToken();
2101  // Special processing for depend(source) clause.
2102  if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
2103  // Parse ')'.
2104  T.consumeClose();
2105  return false;
2106  }
2107  }
2108  if (Tok.is(tok::colon)) {
2109  Data.ColonLoc = ConsumeToken();
2110  } else {
2111  Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
2112  : diag::warn_pragma_expected_colon)
2113  << "dependency type";
2114  }
2115  } else if (Kind == OMPC_linear) {
2116  // Try to parse modifier if any.
2117  if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
2118  Data.LinKind = static_cast<OpenMPLinearClauseKind>(
2119  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2120  Data.DepLinMapLoc = ConsumeToken();
2121  LinearT.consumeOpen();
2122  NeedRParenForLinear = true;
2123  }
2124  } else if (Kind == OMPC_map) {
2125  // Handle map type for map clause.
2126  ColonProtectionRAIIObject ColonRAII(*this);
2127 
2128  // The first identifier may be a list item, a map-type or a
2129  // map-type-modifier. The map-type can also be delete which has the same
2130  // spelling of the C++ delete keyword.
2131  Data.DepLinMapLoc = Tok.getLocation();
2132 
2133  // Check for presence of a colon in the map clause.
2134  TentativeParsingAction TPA(*this);
2135  bool ColonPresent = false;
2136  if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2137  StopBeforeMatch)) {
2138  if (Tok.is(tok::colon))
2139  ColonPresent = true;
2140  }
2141  TPA.Revert();
2142  // Only parse map-type-modifier[s] and map-type if a colon is present in
2143  // the map clause.
2144  if (ColonPresent) {
2145  IsInvalidMapModifier = parseMapTypeModifiers(Data);
2146  if (!IsInvalidMapModifier)
2147  parseMapType(*this, Data);
2148  }
2149  if (Data.MapType == OMPC_MAP_unknown) {
2150  Data.MapType = OMPC_MAP_tofrom;
2151  Data.IsMapTypeImplicit = true;
2152  }
2153 
2154  if (Tok.is(tok::colon))
2155  Data.ColonLoc = ConsumeToken();
2156  }
2157 
2158  bool IsComma =
2159  (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
2160  Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
2161  (Kind == OMPC_reduction && !InvalidReductionId) ||
2162  (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
2163  (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
2164  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
2165  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
2166  Tok.isNot(tok::annot_pragma_openmp_end))) {
2167  ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
2168  // Parse variable
2169  ExprResult VarExpr =
2170  Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2171  if (VarExpr.isUsable()) {
2172  Vars.push_back(VarExpr.get());
2173  } else {
2174  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2175  StopBeforeMatch);
2176  }
2177  // Skip ',' if any
2178  IsComma = Tok.is(tok::comma);
2179  if (IsComma)
2180  ConsumeToken();
2181  else if (Tok.isNot(tok::r_paren) &&
2182  Tok.isNot(tok::annot_pragma_openmp_end) &&
2183  (!MayHaveTail || Tok.isNot(tok::colon)))
2184  Diag(Tok, diag::err_omp_expected_punc)
2185  << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
2186  : getOpenMPClauseName(Kind))
2187  << (Kind == OMPC_flush);
2188  }
2189 
2190  // Parse ')' for linear clause with modifier.
2191  if (NeedRParenForLinear)
2192  LinearT.consumeClose();
2193 
2194  // Parse ':' linear-step (or ':' alignment).
2195  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
2196  if (MustHaveTail) {
2197  Data.ColonLoc = Tok.getLocation();
2198  SourceLocation ELoc = ConsumeToken();
2199  ExprResult Tail = ParseAssignmentExpression();
2200  Tail =
2201  Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
2202  if (Tail.isUsable())
2203  Data.TailExpr = Tail.get();
2204  else
2205  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2206  StopBeforeMatch);
2207  }
2208 
2209  // Parse ')'.
2210  Data.RLoc = Tok.getLocation();
2211  if (!T.consumeClose())
2212  Data.RLoc = T.getCloseLocation();
2213  return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
2214  Vars.empty()) ||
2215  (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
2216  (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
2217  IsInvalidMapModifier;
2218 }
2219 
2220 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
2221 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
2222 /// 'in_reduction'.
2223 ///
2224 /// private-clause:
2225 /// 'private' '(' list ')'
2226 /// firstprivate-clause:
2227 /// 'firstprivate' '(' list ')'
2228 /// lastprivate-clause:
2229 /// 'lastprivate' '(' list ')'
2230 /// shared-clause:
2231 /// 'shared' '(' list ')'
2232 /// linear-clause:
2233 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
2234 /// aligned-clause:
2235 /// 'aligned' '(' list [ ':' alignment ] ')'
2236 /// reduction-clause:
2237 /// 'reduction' '(' reduction-identifier ':' list ')'
2238 /// task_reduction-clause:
2239 /// 'task_reduction' '(' reduction-identifier ':' list ')'
2240 /// in_reduction-clause:
2241 /// 'in_reduction' '(' reduction-identifier ':' list ')'
2242 /// copyprivate-clause:
2243 /// 'copyprivate' '(' list ')'
2244 /// flush-clause:
2245 /// 'flush' '(' list ')'
2246 /// depend-clause:
2247 /// 'depend' '(' in | out | inout : list | source ')'
2248 /// map-clause:
2249 /// 'map' '(' [ [ always [,] ] [ close [,] ]
2250 /// [ mapper(mapper-identifier) [,] ]
2251 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
2252 /// to-clause:
2253 /// 'to' '(' list ')'
2254 /// from-clause:
2255 /// 'from' '(' list ')'
2256 /// use_device_ptr-clause:
2257 /// 'use_device_ptr' '(' list ')'
2258 /// is_device_ptr-clause:
2259 /// 'is_device_ptr' '(' list ')'
2260 ///
2261 /// For 'linear' clause linear-list may have the following forms:
2262 /// list
2263 /// modifier(list)
2264 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
2265 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
2267  bool ParseOnly) {
2268  SourceLocation Loc = Tok.getLocation();
2269  SourceLocation LOpen = ConsumeToken();
2271  OpenMPVarListDataTy Data;
2272 
2273  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
2274  return nullptr;
2275 
2276  if (ParseOnly)
2277  return nullptr;
2278  OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
2279  return Actions.ActOnOpenMPVarListClause(
2280  Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
2282  Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
2283  Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc);
2284 }
2285 
OpenMPDependClauseKind DepKind
Definition: Parser.h:2906
Defines the clang::ASTContext interface.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Called on correct id-expression from the &#39;#pragma omp threadprivate&#39;.
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:986
A (possibly-)qualified type.
Definition: Type.h:634
static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P)
Definition: ParseOpenMP.cpp:84
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:94
DeclarationNameInfo ReductionOrMapperId
Definition: Parser.h:2905
bool isEmpty() const
No scope specifier.
Definition: DeclSpec.h:188
iterator end()
Definition: DeclGroup.h:105
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SmallVector< OpenMPMapModifierKind, OMPMapClause::NumberOfModifiers > MapTypeModifiers
Definition: Parser.h:2909
StringRef P
The base class of the type hierarchy.
Definition: Type.h:1409
SourceLocation getCloseLocation() const
This indicates that the scope corresponds to a function, which means that labels are set here...
Definition: Scope.h:47
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
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:97
void ActOnExitFunctionContext()
Definition: SemaDecl.cpp:1313
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:1764
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:44
RAII object used to temporarily allow the C++ &#39;this&#39; expression to be used, with the given qualifiers...
Definition: Sema.h:5184
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:117
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed...
tok::TokenKind getKind() const
Definition: Token.h:89
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:1080
OpenMPLinearClauseKind LinKind
Definition: Parser.h:2907
The collection of all-type qualifiers we support.
Definition: Type.h:137
OpenMPMapModifierKind
OpenMP modifier kind for &#39;map&#39; clause.
Definition: OpenMPKinds.h:100
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:56
Represents a struct/union/class.
Definition: Decl.h:3592
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:84
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:933
PtrTy get() const
Definition: Ownership.h:170
bool isNot(T Kind) const
Definition: FormatToken.h:322
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.
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:62
IdentifierInfo * getIdentifier() const
Definition: DeclSpec.h:2126
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:313
A RAII object to enter scope of a compound statement.
Definition: Sema.h:3781
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:568
This is the scope of OpenMP executable directive.
Definition: Scope.h:107
Sema & getActions() const
Definition: Parser.h:396
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:399
OpenMPDirectiveKindEx
Definition: ParseOpenMP.cpp:28
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:123
OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:32
DeclContext * getDeclContext()
Definition: DeclBase.h:429
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:395
DeclaratorContext
Definition: DeclSpec.h:1722
SmallVector< SourceLocation, OMPMapClause::NumberOfModifiers > MapTypeModifiersLoc
Definition: Parser.h:2911
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:699
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:1273
Encodes a location in the source.
OpenMPDependClauseKind
OpenMP attributes for &#39;depend&#39; clause.
Definition: OpenMPKinds.h:76
bool is(tok::TokenKind Kind) const
Definition: FormatToken.h:306
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr *> &Vars, OpenMPVarListDataTy &Data)
Parses clauses with list.
static unsigned getOpenMPDirectiveKindEx(StringRef S)
Definition: ParseOpenMP.cpp:65
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:176
OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:22
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:50
Scope * getCurScope() const
Definition: Parser.h:400
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:1888
bool isNot(tok::TokenKind K) const
Definition: Token.h:95
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:2255
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:1013
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:96
Data used for parsing list of variables in OpenMP clauses.
Definition: Parser.h:2900
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
static const TST TST_unspecified
Definition: DeclSpec.h:271
CXXScopeSpec ReductionOrMapperIdScopeSpec
Definition: Parser.h:2904
Not an overloaded operator.
Definition: OperatorKinds.h:22
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
QualType getCanonicalTypeInternal() const
Definition: Type.h:2360
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:1331
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:227
SourceLocation ConsumeToken()
ConsumeToken - Consume the current &#39;peek token&#39; and lex the next one.
Definition: Parser.h:438
OpenMPMapClauseKind
OpenMP mapping kind for &#39;map&#39; clause.
Definition: OpenMPKinds.h:92
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.
This structure contains most locations needed for by an OMPVarListClause.
Definition: OpenMPClause.h:160
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:420
OpenMPMapClauseKind MapType
Definition: Parser.h:2912
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:1737
Stop skipping at specified token, but don&#39;t skip the token itself.
Definition: Parser.h:1062
SourceLocation getEndLoc() const
Definition: Token.h:150