clang  5.0.0
ParseOpenMP.cpp
Go to the documentation of this file.
1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/StmtOpenMP.h"
17 #include "clang/Parse/Parser.h"
19 #include "clang/Sema/Scope.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 
22 using namespace clang;
23 
24 //===----------------------------------------------------------------------===//
25 // OpenMP declarative directives.
26 //===----------------------------------------------------------------------===//
27 
28 namespace {
30  OMPD_cancellation = OMPD_unknown + 1,
31  OMPD_data,
32  OMPD_declare,
33  OMPD_end,
34  OMPD_end_declare,
35  OMPD_enter,
36  OMPD_exit,
37  OMPD_point,
38  OMPD_reduction,
39  OMPD_target_enter,
40  OMPD_target_exit,
41  OMPD_update,
42  OMPD_distribute_parallel,
43  OMPD_teams_distribute_parallel,
44  OMPD_target_teams_distribute_parallel
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  .Default(OMPD_unknown);
81 }
82 
84  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
85  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
86  // TODO: add other combined directives in topological order.
87  static const unsigned F[][3] = {
88  { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
89  { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
90  { OMPD_declare, OMPD_simd, OMPD_declare_simd },
91  { OMPD_declare, OMPD_target, OMPD_declare_target },
92  { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
93  { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
94  { OMPD_distribute_parallel_for, OMPD_simd,
95  OMPD_distribute_parallel_for_simd },
96  { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
97  { OMPD_end, OMPD_declare, OMPD_end_declare },
98  { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
99  { OMPD_target, OMPD_data, OMPD_target_data },
100  { OMPD_target, OMPD_enter, OMPD_target_enter },
101  { OMPD_target, OMPD_exit, OMPD_target_exit },
102  { OMPD_target, OMPD_update, OMPD_target_update },
103  { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
104  { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
105  { OMPD_for, OMPD_simd, OMPD_for_simd },
106  { OMPD_parallel, OMPD_for, OMPD_parallel_for },
107  { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
108  { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
109  { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
110  { OMPD_target, OMPD_parallel, OMPD_target_parallel },
111  { OMPD_target, OMPD_simd, OMPD_target_simd },
112  { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
113  { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
114  { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
115  { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
116  { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
117  { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
118  { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
119  { OMPD_target, OMPD_teams, OMPD_target_teams },
120  { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
121  { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
122  { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
123  { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
124  { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
125  };
126  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
127  auto Tok = P.getCurToken();
128  unsigned DKind =
129  Tok.isAnnotation()
130  ? static_cast<unsigned>(OMPD_unknown)
132  if (DKind == OMPD_unknown)
133  return OMPD_unknown;
134 
135  for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
136  if (DKind != F[i][0])
137  continue;
138 
139  Tok = P.getPreprocessor().LookAhead(0);
140  unsigned SDKind =
141  Tok.isAnnotation()
142  ? static_cast<unsigned>(OMPD_unknown)
144  if (SDKind == OMPD_unknown)
145  continue;
146 
147  if (SDKind == F[i][1]) {
148  P.ConsumeToken();
149  DKind = F[i][2];
150  }
151  }
152  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
153  : OMPD_unknown;
154 }
155 
157  Token Tok = P.getCurToken();
158  Sema &Actions = P.getActions();
160  // Allow to use 'operator' keyword for C++ operators
161  bool WithOperator = false;
162  if (Tok.is(tok::kw_operator)) {
163  P.ConsumeToken();
164  Tok = P.getCurToken();
165  WithOperator = true;
166  }
167  switch (Tok.getKind()) {
168  case tok::plus: // '+'
169  OOK = OO_Plus;
170  break;
171  case tok::minus: // '-'
172  OOK = OO_Minus;
173  break;
174  case tok::star: // '*'
175  OOK = OO_Star;
176  break;
177  case tok::amp: // '&'
178  OOK = OO_Amp;
179  break;
180  case tok::pipe: // '|'
181  OOK = OO_Pipe;
182  break;
183  case tok::caret: // '^'
184  OOK = OO_Caret;
185  break;
186  case tok::ampamp: // '&&'
187  OOK = OO_AmpAmp;
188  break;
189  case tok::pipepipe: // '||'
190  OOK = OO_PipePipe;
191  break;
192  case tok::identifier: // identifier
193  if (!WithOperator)
194  break;
195  LLVM_FALLTHROUGH;
196  default:
197  P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
198  P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
200  return DeclarationName();
201  }
202  P.ConsumeToken();
203  auto &DeclNames = Actions.getASTContext().DeclarationNames;
204  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
205  : DeclNames.getCXXOperatorName(OOK);
206 }
207 
208 /// \brief Parse 'omp declare reduction' construct.
209 ///
210 /// declare-reduction-directive:
211 /// annot_pragma_openmp 'declare' 'reduction'
212 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
213 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
214 /// annot_pragma_openmp_end
215 /// <reduction_id> is either a base language identifier or one of the following
216 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
217 ///
219 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
220  // Parse '('.
221  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
222  if (T.expectAndConsume(diag::err_expected_lparen_after,
223  getOpenMPDirectiveName(OMPD_declare_reduction))) {
224  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
225  return DeclGroupPtrTy();
226  }
227 
229  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
230  return DeclGroupPtrTy();
231 
232  // Consume ':'.
233  bool IsCorrect = !ExpectAndConsume(tok::colon);
234 
235  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
236  return DeclGroupPtrTy();
237 
238  IsCorrect = IsCorrect && !Name.isEmpty();
239 
240  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
241  Diag(Tok.getLocation(), diag::err_expected_type);
242  IsCorrect = false;
243  }
244 
245  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
246  return DeclGroupPtrTy();
247 
249  // Parse list of types until ':' token.
250  do {
251  ColonProtectionRAIIObject ColonRAII(*this);
252  SourceRange Range;
254  if (TR.isUsable()) {
255  auto ReductionType =
256  Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
257  if (!ReductionType.isNull()) {
258  ReductionTypes.push_back(
259  std::make_pair(ReductionType, Range.getBegin()));
260  }
261  } else {
262  SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
264  }
265 
266  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
267  break;
268 
269  // Consume ','.
270  if (ExpectAndConsume(tok::comma)) {
271  IsCorrect = false;
272  if (Tok.is(tok::annot_pragma_openmp_end)) {
273  Diag(Tok.getLocation(), diag::err_expected_type);
274  return DeclGroupPtrTy();
275  }
276  }
277  } while (Tok.isNot(tok::annot_pragma_openmp_end));
278 
279  if (ReductionTypes.empty()) {
280  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
281  return DeclGroupPtrTy();
282  }
283 
284  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
285  return DeclGroupPtrTy();
286 
287  // Consume ':'.
288  if (ExpectAndConsume(tok::colon))
289  IsCorrect = false;
290 
291  if (Tok.is(tok::annot_pragma_openmp_end)) {
292  Diag(Tok.getLocation(), diag::err_expected_expression);
293  return DeclGroupPtrTy();
294  }
295 
297  getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
298 
299  // Parse <combiner> expression and then parse initializer if any for each
300  // correct type.
301  unsigned I = 0, E = ReductionTypes.size();
302  for (auto *D : DRD.get()) {
303  TentativeParsingAction TPA(*this);
304  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
306  // Parse <combiner> expression.
308  ExprResult CombinerResult =
310  D->getLocation(), /*DiscardedValue=*/true);
311  Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
312 
313  if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
314  Tok.isNot(tok::annot_pragma_openmp_end)) {
315  TPA.Commit();
316  IsCorrect = false;
317  break;
318  }
319  IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
320  ExprResult InitializerResult;
321  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
322  // Parse <initializer> expression.
323  if (Tok.is(tok::identifier) &&
324  Tok.getIdentifierInfo()->isStr("initializer"))
325  ConsumeToken();
326  else {
327  Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
328  TPA.Commit();
329  IsCorrect = false;
330  break;
331  }
332  // Parse '('.
333  BalancedDelimiterTracker T(*this, tok::l_paren,
334  tok::annot_pragma_openmp_end);
335  IsCorrect =
336  !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
337  IsCorrect;
338  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
339  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
341  // Parse expression.
343  InitializerResult = Actions.ActOnFinishFullExpr(
344  ParseAssignmentExpression().get(), D->getLocation(),
345  /*DiscardedValue=*/true);
347  D, InitializerResult.get());
348  if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
349  Tok.isNot(tok::annot_pragma_openmp_end)) {
350  TPA.Commit();
351  IsCorrect = false;
352  break;
353  }
354  IsCorrect =
355  !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
356  }
357  }
358 
359  ++I;
360  // Revert parsing if not the last type, otherwise accept it, we're done with
361  // parsing.
362  if (I != E)
363  TPA.Revert();
364  else
365  TPA.Commit();
366  }
368  IsCorrect);
369 }
370 
371 namespace {
372 /// RAII that recreates function context for correct parsing of clauses of
373 /// 'declare simd' construct.
374 /// OpenMP, 2.8.2 declare simd Construct
375 /// The expressions appearing in the clauses of this directive are evaluated in
376 /// the scope of the arguments of the function declaration or definition.
377 class FNContextRAII final {
378  Parser &P;
379  Sema::CXXThisScopeRAII *ThisScope;
380  Parser::ParseScope *TempScope;
381  Parser::ParseScope *FnScope;
382  bool HasTemplateScope = false;
383  bool HasFunScope = false;
384  FNContextRAII() = delete;
385  FNContextRAII(const FNContextRAII &) = delete;
386  FNContextRAII &operator=(const FNContextRAII &) = delete;
387 
388 public:
389  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
390  Decl *D = *Ptr.get().begin();
391  NamedDecl *ND = dyn_cast<NamedDecl>(D);
392  RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
393  Sema &Actions = P.getActions();
394 
395  // Allow 'this' within late-parsed attributes.
396  ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
397  ND && ND->isCXXInstanceMember());
398 
399  // If the Decl is templatized, add template parameters to scope.
400  HasTemplateScope = D->isTemplateDecl();
401  TempScope =
402  new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
403  if (HasTemplateScope)
404  Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
405 
406  // If the Decl is on a function, add function parameters to the scope.
407  HasFunScope = D->isFunctionOrFunctionTemplate();
409  HasFunScope);
410  if (HasFunScope)
411  Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
412  }
413  ~FNContextRAII() {
414  if (HasFunScope) {
416  FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
417  }
418  if (HasTemplateScope)
419  TempScope->Exit();
420  delete FnScope;
421  delete TempScope;
422  delete ThisScope;
423  }
424 };
425 } // namespace
426 
427 /// Parses clauses for 'declare simd' directive.
428 /// clause:
429 /// 'inbranch' | 'notinbranch'
430 /// 'simdlen' '(' <expr> ')'
431 /// { 'uniform' '(' <argument_list> ')' }
432 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
433 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
435  Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
437  SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
438  SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
439  SourceRange BSRange;
440  const Token &Tok = P.getCurToken();
441  bool IsError = false;
442  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
443  if (Tok.isNot(tok::identifier))
444  break;
445  OMPDeclareSimdDeclAttr::BranchStateTy Out;
446  IdentifierInfo *II = Tok.getIdentifierInfo();
447  StringRef ClauseName = II->getName();
448  // Parse 'inranch|notinbranch' clauses.
449  if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
450  if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
451  P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
452  << ClauseName
453  << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
454  IsError = true;
455  }
456  BS = Out;
457  BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
458  P.ConsumeToken();
459  } else if (ClauseName.equals("simdlen")) {
460  if (SimdLen.isUsable()) {
461  P.Diag(Tok, diag::err_omp_more_one_clause)
462  << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
463  IsError = true;
464  }
465  P.ConsumeToken();
466  SourceLocation RLoc;
467  SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
468  if (SimdLen.isInvalid())
469  IsError = true;
470  } else {
471  OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
472  if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
473  CKind == OMPC_linear) {
475  auto *Vars = &Uniforms;
476  if (CKind == OMPC_aligned)
477  Vars = &Aligneds;
478  else if (CKind == OMPC_linear)
479  Vars = &Linears;
480 
481  P.ConsumeToken();
482  if (P.ParseOpenMPVarList(OMPD_declare_simd,
483  getOpenMPClauseKind(ClauseName), *Vars, Data))
484  IsError = true;
485  if (CKind == OMPC_aligned)
486  Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
487  else if (CKind == OMPC_linear) {
489  Data.DepLinMapLoc))
490  Data.LinKind = OMPC_LINEAR_val;
491  LinModifiers.append(Linears.size() - LinModifiers.size(),
492  Data.LinKind);
493  Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
494  }
495  } else
496  // TODO: add parsing of other clauses.
497  break;
498  }
499  // Skip ',' if any.
500  if (Tok.is(tok::comma))
501  P.ConsumeToken();
502  }
503  return IsError;
504 }
505 
506 /// Parse clauses for '#pragma omp declare simd'.
508 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
509  CachedTokens &Toks, SourceLocation Loc) {
510  PP.EnterToken(Tok);
511  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
512  // Consume the previously pushed token.
513  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
514 
515  FNContextRAII FnContext(*this, Ptr);
516  OMPDeclareSimdDeclAttr::BranchStateTy BS =
517  OMPDeclareSimdDeclAttr::BS_Undefined;
518  ExprResult Simdlen;
519  SmallVector<Expr *, 4> Uniforms;
520  SmallVector<Expr *, 4> Aligneds;
521  SmallVector<Expr *, 4> Alignments;
522  SmallVector<Expr *, 4> Linears;
523  SmallVector<unsigned, 4> LinModifiers;
525  bool IsError =
526  parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
527  Alignments, Linears, LinModifiers, Steps);
528  // Need to check for extra tokens.
529  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
530  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
531  << getOpenMPDirectiveName(OMPD_declare_simd);
532  while (Tok.isNot(tok::annot_pragma_openmp_end))
533  ConsumeAnyToken();
534  }
535  // Skip the last annot_pragma_openmp_end.
536  SourceLocation EndLoc = ConsumeAnnotationToken();
537  if (!IsError) {
538  return Actions.ActOnOpenMPDeclareSimdDirective(
539  Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
540  LinModifiers, Steps, SourceRange(Loc, EndLoc));
541  }
542  return Ptr;
543 }
544 
545 /// \brief Parsing of declarative OpenMP directives.
546 ///
547 /// threadprivate-directive:
548 /// annot_pragma_openmp 'threadprivate' simple-variable-list
549 /// annot_pragma_openmp_end
550 ///
551 /// declare-reduction-directive:
552 /// annot_pragma_openmp 'declare' 'reduction' [...]
553 /// annot_pragma_openmp_end
554 ///
555 /// declare-simd-directive:
556 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
557 /// annot_pragma_openmp_end
558 /// <function declaration/definition>
559 ///
560 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
561  AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
562  DeclSpec::TST TagType, Decl *Tag) {
563  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
564  ParenBraceBracketBalancer BalancerRAIIObj(*this);
565 
566  SourceLocation Loc = ConsumeAnnotationToken();
567  auto DKind = ParseOpenMPDirectiveKind(*this);
568 
569  switch (DKind) {
570  case OMPD_threadprivate: {
571  ConsumeToken();
572  ThreadprivateListParserHelper Helper(this);
573  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
574  // The last seen token is annot_pragma_openmp_end - need to check for
575  // extra tokens.
576  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
577  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
578  << getOpenMPDirectiveName(OMPD_threadprivate);
579  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
580  }
581  // Skip the last annot_pragma_openmp_end.
582  ConsumeAnnotationToken();
583  return Actions.ActOnOpenMPThreadprivateDirective(Loc,
584  Helper.getIdentifiers());
585  }
586  break;
587  }
588  case OMPD_declare_reduction:
589  ConsumeToken();
590  if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
591  // The last seen token is annot_pragma_openmp_end - need to check for
592  // extra tokens.
593  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
594  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
595  << getOpenMPDirectiveName(OMPD_declare_reduction);
596  while (Tok.isNot(tok::annot_pragma_openmp_end))
597  ConsumeAnyToken();
598  }
599  // Skip the last annot_pragma_openmp_end.
600  ConsumeAnnotationToken();
601  return Res;
602  }
603  break;
604  case OMPD_declare_simd: {
605  // The syntax is:
606  // { #pragma omp declare simd }
607  // <function-declaration-or-definition>
608  //
609  ConsumeToken();
610  CachedTokens Toks;
611  while(Tok.isNot(tok::annot_pragma_openmp_end)) {
612  Toks.push_back(Tok);
613  ConsumeAnyToken();
614  }
615  Toks.push_back(Tok);
616  ConsumeAnyToken();
617 
618  DeclGroupPtrTy Ptr;
619  if (Tok.is(tok::annot_pragma_openmp))
620  Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
621  else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
622  // Here we expect to see some function declaration.
623  if (AS == AS_none) {
624  assert(TagType == DeclSpec::TST_unspecified);
625  MaybeParseCXX11Attributes(Attrs);
626  ParsingDeclSpec PDS(*this);
627  Ptr = ParseExternalDeclaration(Attrs, &PDS);
628  } else {
629  Ptr =
630  ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
631  }
632  }
633  if (!Ptr) {
634  Diag(Loc, diag::err_omp_decl_in_declare_simd);
635  return DeclGroupPtrTy();
636  }
637  return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
638  }
639  case OMPD_declare_target: {
640  SourceLocation DTLoc = ConsumeAnyToken();
641  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
642  // OpenMP 4.5 syntax with list of entities.
644  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
645  OMPDeclareTargetDeclAttr::MapTypeTy MT =
646  OMPDeclareTargetDeclAttr::MT_To;
647  if (Tok.is(tok::identifier)) {
648  IdentifierInfo *II = Tok.getIdentifierInfo();
649  StringRef ClauseName = II->getName();
650  // Parse 'to|link' clauses.
651  if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
652  MT)) {
653  Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
654  << ClauseName;
655  break;
656  }
657  ConsumeToken();
658  }
659  auto Callback = [this, MT, &SameDirectiveDecls](
660  CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
661  Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
662  SameDirectiveDecls);
663  };
664  if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
665  break;
666 
667  // Consume optional ','.
668  if (Tok.is(tok::comma))
669  ConsumeToken();
670  }
671  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
672  ConsumeAnyToken();
673  return DeclGroupPtrTy();
674  }
675 
676  // Skip the last annot_pragma_openmp_end.
677  ConsumeAnyToken();
678 
679  if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
680  return DeclGroupPtrTy();
681 
682  DKind = ParseOpenMPDirectiveKind(*this);
683  while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
684  Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
685  ParsedAttributesWithRange attrs(AttrFactory);
686  MaybeParseCXX11Attributes(attrs);
687  ParseExternalDeclaration(attrs);
688  if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
689  TentativeParsingAction TPA(*this);
690  ConsumeAnnotationToken();
691  DKind = ParseOpenMPDirectiveKind(*this);
692  if (DKind != OMPD_end_declare_target)
693  TPA.Revert();
694  else
695  TPA.Commit();
696  }
697  }
698 
699  if (DKind == OMPD_end_declare_target) {
700  ConsumeAnyToken();
701  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
702  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
703  << getOpenMPDirectiveName(OMPD_end_declare_target);
704  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
705  }
706  // Skip the last annot_pragma_openmp_end.
707  ConsumeAnyToken();
708  } else {
709  Diag(Tok, diag::err_expected_end_declare_target);
710  Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
711  }
712  Actions.ActOnFinishOpenMPDeclareTargetDirective();
713  return DeclGroupPtrTy();
714  }
715  case OMPD_unknown:
716  Diag(Tok, diag::err_omp_unknown_directive);
717  break;
718  case OMPD_parallel:
719  case OMPD_simd:
720  case OMPD_task:
721  case OMPD_taskyield:
722  case OMPD_barrier:
723  case OMPD_taskwait:
724  case OMPD_taskgroup:
725  case OMPD_flush:
726  case OMPD_for:
727  case OMPD_for_simd:
728  case OMPD_sections:
729  case OMPD_section:
730  case OMPD_single:
731  case OMPD_master:
732  case OMPD_ordered:
733  case OMPD_critical:
734  case OMPD_parallel_for:
735  case OMPD_parallel_for_simd:
736  case OMPD_parallel_sections:
737  case OMPD_atomic:
738  case OMPD_target:
739  case OMPD_teams:
740  case OMPD_cancellation_point:
741  case OMPD_cancel:
742  case OMPD_target_data:
743  case OMPD_target_enter_data:
744  case OMPD_target_exit_data:
745  case OMPD_target_parallel:
746  case OMPD_target_parallel_for:
747  case OMPD_taskloop:
748  case OMPD_taskloop_simd:
749  case OMPD_distribute:
750  case OMPD_end_declare_target:
751  case OMPD_target_update:
752  case OMPD_distribute_parallel_for:
753  case OMPD_distribute_parallel_for_simd:
754  case OMPD_distribute_simd:
755  case OMPD_target_parallel_for_simd:
756  case OMPD_target_simd:
757  case OMPD_teams_distribute:
758  case OMPD_teams_distribute_simd:
759  case OMPD_teams_distribute_parallel_for_simd:
760  case OMPD_teams_distribute_parallel_for:
761  case OMPD_target_teams:
762  case OMPD_target_teams_distribute:
763  case OMPD_target_teams_distribute_parallel_for:
764  case OMPD_target_teams_distribute_parallel_for_simd:
765  case OMPD_target_teams_distribute_simd:
766  Diag(Tok, diag::err_omp_unexpected_directive)
767  << getOpenMPDirectiveName(DKind);
768  break;
769  }
770  while (Tok.isNot(tok::annot_pragma_openmp_end))
771  ConsumeAnyToken();
772  ConsumeAnyToken();
773  return nullptr;
774 }
775 
776 /// \brief Parsing of declarative or executable OpenMP directives.
777 ///
778 /// threadprivate-directive:
779 /// annot_pragma_openmp 'threadprivate' simple-variable-list
780 /// annot_pragma_openmp_end
781 ///
782 /// declare-reduction-directive:
783 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
784 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
785 /// ('omp_priv' '=' <expression>|<function_call>) ')']
786 /// annot_pragma_openmp_end
787 ///
788 /// executable-directive:
789 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
790 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
791 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
792 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
793 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
794 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
795 /// 'distribute' | 'target enter data' | 'target exit data' |
796 /// 'target parallel' | 'target parallel for' |
797 /// 'target update' | 'distribute parallel for' |
798 /// 'distribute paralle for simd' | 'distribute simd' |
799 /// 'target parallel for simd' | 'target simd' |
800 /// 'teams distribute' | 'teams distribute simd' |
801 /// 'teams distribute parallel for simd' |
802 /// 'teams distribute parallel for' | 'target teams' |
803 /// 'target teams distribute' |
804 /// 'target teams distribute parallel for' |
805 /// 'target teams distribute parallel for simd' |
806 /// 'target teams distribute simd' {clause}
807 /// annot_pragma_openmp_end
808 ///
809 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
810  AllowedConstructsKind Allowed) {
811  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
812  ParenBraceBracketBalancer BalancerRAIIObj(*this);
815  FirstClauses(OMPC_unknown + 1);
816  unsigned ScopeFlags =
818  SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
819  auto DKind = ParseOpenMPDirectiveKind(*this);
820  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
821  // Name of critical directive.
822  DeclarationNameInfo DirName;
824  bool HasAssociatedStatement = true;
825  bool FlushHasClause = false;
826 
827  switch (DKind) {
828  case OMPD_threadprivate: {
829  if (Allowed != ACK_Any) {
830  Diag(Tok, diag::err_omp_immediate_directive)
831  << getOpenMPDirectiveName(DKind) << 0;
832  }
833  ConsumeToken();
834  ThreadprivateListParserHelper Helper(this);
835  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
836  // The last seen token is annot_pragma_openmp_end - need to check for
837  // extra tokens.
838  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
839  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
840  << getOpenMPDirectiveName(OMPD_threadprivate);
841  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
842  }
843  DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
844  Loc, Helper.getIdentifiers());
845  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
846  }
847  SkipUntil(tok::annot_pragma_openmp_end);
848  break;
849  }
850  case OMPD_declare_reduction:
851  ConsumeToken();
852  if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
853  // The last seen token is annot_pragma_openmp_end - need to check for
854  // extra tokens.
855  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
856  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
857  << getOpenMPDirectiveName(OMPD_declare_reduction);
858  while (Tok.isNot(tok::annot_pragma_openmp_end))
859  ConsumeAnyToken();
860  }
861  ConsumeAnyToken();
862  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
863  } else
864  SkipUntil(tok::annot_pragma_openmp_end);
865  break;
866  case OMPD_flush:
867  if (PP.LookAhead(0).is(tok::l_paren)) {
868  FlushHasClause = true;
869  // Push copy of the current token back to stream to properly parse
870  // pseudo-clause OMPFlushClause.
871  PP.EnterToken(Tok);
872  }
873  LLVM_FALLTHROUGH;
874  case OMPD_taskyield:
875  case OMPD_barrier:
876  case OMPD_taskwait:
877  case OMPD_cancellation_point:
878  case OMPD_cancel:
879  case OMPD_target_enter_data:
880  case OMPD_target_exit_data:
881  case OMPD_target_update:
882  if (Allowed == ACK_StatementsOpenMPNonStandalone) {
883  Diag(Tok, diag::err_omp_immediate_directive)
884  << getOpenMPDirectiveName(DKind) << 0;
885  }
886  HasAssociatedStatement = false;
887  // Fall through for further analysis.
888  LLVM_FALLTHROUGH;
889  case OMPD_parallel:
890  case OMPD_simd:
891  case OMPD_for:
892  case OMPD_for_simd:
893  case OMPD_sections:
894  case OMPD_single:
895  case OMPD_section:
896  case OMPD_master:
897  case OMPD_critical:
898  case OMPD_parallel_for:
899  case OMPD_parallel_for_simd:
900  case OMPD_parallel_sections:
901  case OMPD_task:
902  case OMPD_ordered:
903  case OMPD_atomic:
904  case OMPD_target:
905  case OMPD_teams:
906  case OMPD_taskgroup:
907  case OMPD_target_data:
908  case OMPD_target_parallel:
909  case OMPD_target_parallel_for:
910  case OMPD_taskloop:
911  case OMPD_taskloop_simd:
912  case OMPD_distribute:
913  case OMPD_distribute_parallel_for:
914  case OMPD_distribute_parallel_for_simd:
915  case OMPD_distribute_simd:
916  case OMPD_target_parallel_for_simd:
917  case OMPD_target_simd:
918  case OMPD_teams_distribute:
919  case OMPD_teams_distribute_simd:
920  case OMPD_teams_distribute_parallel_for_simd:
921  case OMPD_teams_distribute_parallel_for:
922  case OMPD_target_teams:
923  case OMPD_target_teams_distribute:
924  case OMPD_target_teams_distribute_parallel_for:
925  case OMPD_target_teams_distribute_parallel_for_simd:
926  case OMPD_target_teams_distribute_simd: {
927  ConsumeToken();
928  // Parse directive name of the 'critical' directive if any.
929  if (DKind == OMPD_critical) {
930  BalancedDelimiterTracker T(*this, tok::l_paren,
931  tok::annot_pragma_openmp_end);
932  if (!T.consumeOpen()) {
933  if (Tok.isAnyIdentifier()) {
934  DirName =
936  ConsumeAnyToken();
937  } else {
938  Diag(Tok, diag::err_omp_expected_identifier_for_critical);
939  }
940  T.consumeClose();
941  }
942  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
943  CancelRegion = ParseOpenMPDirectiveKind(*this);
944  if (Tok.isNot(tok::annot_pragma_openmp_end))
945  ConsumeToken();
946  }
947 
948  if (isOpenMPLoopDirective(DKind))
949  ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
950  if (isOpenMPSimdDirective(DKind))
951  ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
952  ParseScope OMPDirectiveScope(this, ScopeFlags);
953  Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
954 
955  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
956  OpenMPClauseKind CKind =
957  Tok.isAnnotation()
958  ? OMPC_unknown
959  : FlushHasClause ? OMPC_flush
960  : getOpenMPClauseKind(PP.getSpelling(Tok));
961  Actions.StartOpenMPClause(CKind);
962  FlushHasClause = false;
963  OMPClause *Clause =
964  ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
965  FirstClauses[CKind].setInt(true);
966  if (Clause) {
967  FirstClauses[CKind].setPointer(Clause);
968  Clauses.push_back(Clause);
969  }
970 
971  // Skip ',' if any.
972  if (Tok.is(tok::comma))
973  ConsumeToken();
974  Actions.EndOpenMPClause();
975  }
976  // End location of the directive.
977  EndLoc = Tok.getLocation();
978  // Consume final annot_pragma_openmp_end.
979  ConsumeAnnotationToken();
980 
981  // OpenMP [2.13.8, ordered Construct, Syntax]
982  // If the depend clause is specified, the ordered construct is a stand-alone
983  // directive.
984  if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
985  if (Allowed == ACK_StatementsOpenMPNonStandalone) {
986  Diag(Loc, diag::err_omp_immediate_directive)
987  << getOpenMPDirectiveName(DKind) << 1
988  << getOpenMPClauseName(OMPC_depend);
989  }
990  HasAssociatedStatement = false;
991  }
992 
993  StmtResult AssociatedStmt;
994  if (HasAssociatedStatement) {
995  // The body is a block scope like in Lambdas and Blocks.
996  Sema::CompoundScopeRAII CompoundScope(Actions);
997  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
998  Actions.ActOnStartOfCompoundStmt();
999  // Parse statement
1000  AssociatedStmt = ParseStatement();
1001  Actions.ActOnFinishOfCompoundStmt();
1002  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1003  }
1004  Directive = Actions.ActOnOpenMPExecutableDirective(
1005  DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1006  EndLoc);
1007 
1008  // Exit scope.
1009  Actions.EndOpenMPDSABlock(Directive.get());
1010  OMPDirectiveScope.Exit();
1011  break;
1012  }
1013  case OMPD_declare_simd:
1014  case OMPD_declare_target:
1015  case OMPD_end_declare_target:
1016  Diag(Tok, diag::err_omp_unexpected_directive)
1017  << getOpenMPDirectiveName(DKind);
1018  SkipUntil(tok::annot_pragma_openmp_end);
1019  break;
1020  case OMPD_unknown:
1021  Diag(Tok, diag::err_omp_unknown_directive);
1022  SkipUntil(tok::annot_pragma_openmp_end);
1023  break;
1024  }
1025  return Directive;
1026 }
1027 
1028 // Parses simple list:
1029 // simple-variable-list:
1030 // '(' id-expression {, id-expression} ')'
1031 //
1032 bool Parser::ParseOpenMPSimpleVarList(
1034  const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1035  Callback,
1036  bool AllowScopeSpecifier) {
1037  // Parse '('.
1038  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1039  if (T.expectAndConsume(diag::err_expected_lparen_after,
1040  getOpenMPDirectiveName(Kind)))
1041  return true;
1042  bool IsCorrect = true;
1043  bool NoIdentIsFound = true;
1044 
1045  // Read tokens while ')' or annot_pragma_openmp_end is not found.
1046  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1047  CXXScopeSpec SS;
1048  SourceLocation TemplateKWLoc;
1050  // Read var name.
1051  Token PrevTok = Tok;
1052  NoIdentIsFound = false;
1053 
1054  if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1055  ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1056  IsCorrect = false;
1057  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1058  StopBeforeMatch);
1059  } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1060  TemplateKWLoc, Name)) {
1061  IsCorrect = false;
1062  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1063  StopBeforeMatch);
1064  } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1065  Tok.isNot(tok::annot_pragma_openmp_end)) {
1066  IsCorrect = false;
1067  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1068  StopBeforeMatch);
1069  Diag(PrevTok.getLocation(), diag::err_expected)
1070  << tok::identifier
1071  << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1072  } else {
1073  Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1074  }
1075  // Consume ','.
1076  if (Tok.is(tok::comma)) {
1077  ConsumeToken();
1078  }
1079  }
1080 
1081  if (NoIdentIsFound) {
1082  Diag(Tok, diag::err_expected) << tok::identifier;
1083  IsCorrect = false;
1084  }
1085 
1086  // Parse ')'.
1087  IsCorrect = !T.consumeClose() && IsCorrect;
1088 
1089  return !IsCorrect;
1090 }
1091 
1092 /// \brief Parsing of OpenMP clauses.
1093 ///
1094 /// clause:
1095 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1096 /// default-clause | private-clause | firstprivate-clause | shared-clause
1097 /// | linear-clause | aligned-clause | collapse-clause |
1098 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1099 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1100 /// mergeable-clause | flush-clause | read-clause | write-clause |
1101 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1102 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1103 /// thread_limit-clause | priority-clause | grainsize-clause |
1104 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1105 /// from-clause | is_device_ptr-clause | task_reduction-clause
1106 ///
1107 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1108  OpenMPClauseKind CKind, bool FirstClause) {
1109  OMPClause *Clause = nullptr;
1110  bool ErrorFound = false;
1111  // Check if clause is allowed for the given directive.
1112  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1113  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1114  << getOpenMPDirectiveName(DKind);
1115  ErrorFound = true;
1116  }
1117 
1118  switch (CKind) {
1119  case OMPC_final:
1120  case OMPC_num_threads:
1121  case OMPC_safelen:
1122  case OMPC_simdlen:
1123  case OMPC_collapse:
1124  case OMPC_ordered:
1125  case OMPC_device:
1126  case OMPC_num_teams:
1127  case OMPC_thread_limit:
1128  case OMPC_priority:
1129  case OMPC_grainsize:
1130  case OMPC_num_tasks:
1131  case OMPC_hint:
1132  // OpenMP [2.5, Restrictions]
1133  // At most one num_threads clause can appear on the directive.
1134  // OpenMP [2.8.1, simd construct, Restrictions]
1135  // Only one safelen clause can appear on a simd directive.
1136  // Only one simdlen clause can appear on a simd directive.
1137  // Only one collapse clause can appear on a simd directive.
1138  // OpenMP [2.9.1, target data construct, Restrictions]
1139  // At most one device clause can appear on the directive.
1140  // OpenMP [2.11.1, task Construct, Restrictions]
1141  // At most one if clause can appear on the directive.
1142  // At most one final clause can appear on the directive.
1143  // OpenMP [teams Construct, Restrictions]
1144  // At most one num_teams clause can appear on the directive.
1145  // At most one thread_limit clause can appear on the directive.
1146  // OpenMP [2.9.1, task Construct, Restrictions]
1147  // At most one priority clause can appear on the directive.
1148  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1149  // At most one grainsize clause can appear on the directive.
1150  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1151  // At most one num_tasks clause can appear on the directive.
1152  if (!FirstClause) {
1153  Diag(Tok, diag::err_omp_more_one_clause)
1154  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1155  ErrorFound = true;
1156  }
1157 
1158  if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1159  Clause = ParseOpenMPClause(CKind);
1160  else
1161  Clause = ParseOpenMPSingleExprClause(CKind);
1162  break;
1163  case OMPC_default:
1164  case OMPC_proc_bind:
1165  // OpenMP [2.14.3.1, Restrictions]
1166  // Only a single default clause may be specified on a parallel, task or
1167  // teams directive.
1168  // OpenMP [2.5, parallel Construct, Restrictions]
1169  // At most one proc_bind clause can appear on the directive.
1170  if (!FirstClause) {
1171  Diag(Tok, diag::err_omp_more_one_clause)
1172  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1173  ErrorFound = true;
1174  }
1175 
1176  Clause = ParseOpenMPSimpleClause(CKind);
1177  break;
1178  case OMPC_schedule:
1179  case OMPC_dist_schedule:
1180  case OMPC_defaultmap:
1181  // OpenMP [2.7.1, Restrictions, p. 3]
1182  // Only one schedule clause can appear on a loop directive.
1183  // OpenMP [2.10.4, Restrictions, p. 106]
1184  // At most one defaultmap clause can appear on the directive.
1185  if (!FirstClause) {
1186  Diag(Tok, diag::err_omp_more_one_clause)
1187  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1188  ErrorFound = true;
1189  }
1190  LLVM_FALLTHROUGH;
1191 
1192  case OMPC_if:
1193  Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1194  break;
1195  case OMPC_nowait:
1196  case OMPC_untied:
1197  case OMPC_mergeable:
1198  case OMPC_read:
1199  case OMPC_write:
1200  case OMPC_update:
1201  case OMPC_capture:
1202  case OMPC_seq_cst:
1203  case OMPC_threads:
1204  case OMPC_simd:
1205  case OMPC_nogroup:
1206  // OpenMP [2.7.1, Restrictions, p. 9]
1207  // Only one ordered clause can appear on a loop directive.
1208  // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1209  // Only one nowait clause can appear on a for directive.
1210  if (!FirstClause) {
1211  Diag(Tok, diag::err_omp_more_one_clause)
1212  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1213  ErrorFound = true;
1214  }
1215 
1216  Clause = ParseOpenMPClause(CKind);
1217  break;
1218  case OMPC_private:
1219  case OMPC_firstprivate:
1220  case OMPC_lastprivate:
1221  case OMPC_shared:
1222  case OMPC_reduction:
1223  case OMPC_task_reduction:
1224  case OMPC_linear:
1225  case OMPC_aligned:
1226  case OMPC_copyin:
1227  case OMPC_copyprivate:
1228  case OMPC_flush:
1229  case OMPC_depend:
1230  case OMPC_map:
1231  case OMPC_to:
1232  case OMPC_from:
1233  case OMPC_use_device_ptr:
1234  case OMPC_is_device_ptr:
1235  Clause = ParseOpenMPVarListClause(DKind, CKind);
1236  break;
1237  case OMPC_unknown:
1238  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1239  << getOpenMPDirectiveName(DKind);
1240  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1241  break;
1242  case OMPC_threadprivate:
1243  case OMPC_uniform:
1244  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1245  << getOpenMPDirectiveName(DKind);
1246  SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1247  break;
1248  }
1249  return ErrorFound ? nullptr : Clause;
1250 }
1251 
1252 /// Parses simple expression in parens for single-expression clauses of OpenMP
1253 /// constructs.
1254 /// \param RLoc Returned location of right paren.
1256  SourceLocation &RLoc) {
1257  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1258  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1259  return ExprError();
1260 
1261  SourceLocation ELoc = Tok.getLocation();
1262  ExprResult LHS(ParseCastExpression(
1263  /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1264  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1265  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1266 
1267  // Parse ')'.
1268  T.consumeClose();
1269 
1270  RLoc = T.getCloseLocation();
1271  return Val;
1272 }
1273 
1274 /// \brief Parsing of OpenMP clauses with single expressions like 'final',
1275 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1276 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1277 ///
1278 /// final-clause:
1279 /// 'final' '(' expression ')'
1280 ///
1281 /// num_threads-clause:
1282 /// 'num_threads' '(' expression ')'
1283 ///
1284 /// safelen-clause:
1285 /// 'safelen' '(' expression ')'
1286 ///
1287 /// simdlen-clause:
1288 /// 'simdlen' '(' expression ')'
1289 ///
1290 /// collapse-clause:
1291 /// 'collapse' '(' expression ')'
1292 ///
1293 /// priority-clause:
1294 /// 'priority' '(' expression ')'
1295 ///
1296 /// grainsize-clause:
1297 /// 'grainsize' '(' expression ')'
1298 ///
1299 /// num_tasks-clause:
1300 /// 'num_tasks' '(' expression ')'
1301 ///
1302 /// hint-clause:
1303 /// 'hint' '(' expression ')'
1304 ///
1305 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
1306  SourceLocation Loc = ConsumeToken();
1307  SourceLocation LLoc = Tok.getLocation();
1308  SourceLocation RLoc;
1309 
1311 
1312  if (Val.isInvalid())
1313  return nullptr;
1314 
1315  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1316 }
1317 
1318 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1319 ///
1320 /// default-clause:
1321 /// 'default' '(' 'none' | 'shared' ')
1322 ///
1323 /// proc_bind-clause:
1324 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1325 ///
1326 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
1327  SourceLocation Loc = Tok.getLocation();
1328  SourceLocation LOpen = ConsumeToken();
1329  // Parse '('.
1330  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1331  if (T.expectAndConsume(diag::err_expected_lparen_after,
1332  getOpenMPClauseName(Kind)))
1333  return nullptr;
1334 
1335  unsigned Type = getOpenMPSimpleClauseType(
1336  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1338  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1339  Tok.isNot(tok::annot_pragma_openmp_end))
1340  ConsumeAnyToken();
1341 
1342  // Parse ')'.
1343  T.consumeClose();
1344 
1345  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1346  Tok.getLocation());
1347 }
1348 
1349 /// \brief Parsing of OpenMP clauses like 'ordered'.
1350 ///
1351 /// ordered-clause:
1352 /// 'ordered'
1353 ///
1354 /// nowait-clause:
1355 /// 'nowait'
1356 ///
1357 /// untied-clause:
1358 /// 'untied'
1359 ///
1360 /// mergeable-clause:
1361 /// 'mergeable'
1362 ///
1363 /// read-clause:
1364 /// 'read'
1365 ///
1366 /// threads-clause:
1367 /// 'threads'
1368 ///
1369 /// simd-clause:
1370 /// 'simd'
1371 ///
1372 /// nogroup-clause:
1373 /// 'nogroup'
1374 ///
1375 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
1376  SourceLocation Loc = Tok.getLocation();
1377  ConsumeAnyToken();
1378 
1379  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1380 }
1381 
1382 
1383 /// \brief Parsing of OpenMP clauses with single expressions and some additional
1384 /// argument like 'schedule' or 'dist_schedule'.
1385 ///
1386 /// schedule-clause:
1387 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1388 /// ')'
1389 ///
1390 /// if-clause:
1391 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1392 ///
1393 /// defaultmap:
1394 /// 'defaultmap' '(' modifier ':' kind ')'
1395 ///
1396 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
1397  SourceLocation Loc = ConsumeToken();
1398  SourceLocation DelimLoc;
1399  // Parse '('.
1400  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1401  if (T.expectAndConsume(diag::err_expected_lparen_after,
1402  getOpenMPClauseName(Kind)))
1403  return nullptr;
1404 
1405  ExprResult Val;
1408  if (Kind == OMPC_schedule) {
1409  enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1410  Arg.resize(NumberOfElements);
1411  KLoc.resize(NumberOfElements);
1412  Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1413  Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1414  Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1415  auto KindModifier = getOpenMPSimpleClauseType(
1416  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1417  if (KindModifier > OMPC_SCHEDULE_unknown) {
1418  // Parse 'modifier'
1419  Arg[Modifier1] = KindModifier;
1420  KLoc[Modifier1] = Tok.getLocation();
1421  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1422  Tok.isNot(tok::annot_pragma_openmp_end))
1423  ConsumeAnyToken();
1424  if (Tok.is(tok::comma)) {
1425  // Parse ',' 'modifier'
1426  ConsumeAnyToken();
1427  KindModifier = getOpenMPSimpleClauseType(
1428  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1429  Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1430  ? KindModifier
1432  KLoc[Modifier2] = Tok.getLocation();
1433  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1434  Tok.isNot(tok::annot_pragma_openmp_end))
1435  ConsumeAnyToken();
1436  }
1437  // Parse ':'
1438  if (Tok.is(tok::colon))
1439  ConsumeAnyToken();
1440  else
1441  Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1442  KindModifier = getOpenMPSimpleClauseType(
1443  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1444  }
1445  Arg[ScheduleKind] = KindModifier;
1446  KLoc[ScheduleKind] = Tok.getLocation();
1447  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1448  Tok.isNot(tok::annot_pragma_openmp_end))
1449  ConsumeAnyToken();
1450  if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1451  Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1452  Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1453  Tok.is(tok::comma))
1454  DelimLoc = ConsumeAnyToken();
1455  } else if (Kind == OMPC_dist_schedule) {
1456  Arg.push_back(getOpenMPSimpleClauseType(
1457  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1458  KLoc.push_back(Tok.getLocation());
1459  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1460  Tok.isNot(tok::annot_pragma_openmp_end))
1461  ConsumeAnyToken();
1462  if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1463  DelimLoc = ConsumeAnyToken();
1464  } else if (Kind == OMPC_defaultmap) {
1465  // Get a defaultmap modifier
1466  Arg.push_back(getOpenMPSimpleClauseType(
1467  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1468  KLoc.push_back(Tok.getLocation());
1469  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1470  Tok.isNot(tok::annot_pragma_openmp_end))
1471  ConsumeAnyToken();
1472  // Parse ':'
1473  if (Tok.is(tok::colon))
1474  ConsumeAnyToken();
1475  else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1476  Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1477  // Get a defaultmap kind
1478  Arg.push_back(getOpenMPSimpleClauseType(
1479  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1480  KLoc.push_back(Tok.getLocation());
1481  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1482  Tok.isNot(tok::annot_pragma_openmp_end))
1483  ConsumeAnyToken();
1484  } else {
1485  assert(Kind == OMPC_if);
1486  KLoc.push_back(Tok.getLocation());
1487  TentativeParsingAction TPA(*this);
1488  Arg.push_back(ParseOpenMPDirectiveKind(*this));
1489  if (Arg.back() != OMPD_unknown) {
1490  ConsumeToken();
1491  if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1492  TPA.Commit();
1493  DelimLoc = ConsumeToken();
1494  } else {
1495  TPA.Revert();
1496  Arg.back() = OMPD_unknown;
1497  }
1498  } else
1499  TPA.Revert();
1500  }
1501 
1502  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1503  (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1504  Kind == OMPC_if;
1505  if (NeedAnExpression) {
1506  SourceLocation ELoc = Tok.getLocation();
1507  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
1508  Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
1509  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1510  }
1511 
1512  // Parse ')'.
1513  T.consumeClose();
1514 
1515  if (NeedAnExpression && Val.isInvalid())
1516  return nullptr;
1517 
1518  return Actions.ActOnOpenMPSingleExprWithArgClause(
1519  Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1520  T.getCloseLocation());
1521 }
1522 
1523 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
1524  UnqualifiedId &ReductionId) {
1525  SourceLocation TemplateKWLoc;
1526  if (ReductionIdScopeSpec.isEmpty()) {
1527  auto OOK = OO_None;
1528  switch (P.getCurToken().getKind()) {
1529  case tok::plus:
1530  OOK = OO_Plus;
1531  break;
1532  case tok::minus:
1533  OOK = OO_Minus;
1534  break;
1535  case tok::star:
1536  OOK = OO_Star;
1537  break;
1538  case tok::amp:
1539  OOK = OO_Amp;
1540  break;
1541  case tok::pipe:
1542  OOK = OO_Pipe;
1543  break;
1544  case tok::caret:
1545  OOK = OO_Caret;
1546  break;
1547  case tok::ampamp:
1548  OOK = OO_AmpAmp;
1549  break;
1550  case tok::pipepipe:
1551  OOK = OO_PipePipe;
1552  break;
1553  default:
1554  break;
1555  }
1556  if (OOK != OO_None) {
1557  SourceLocation OpLoc = P.ConsumeToken();
1558  SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
1559  ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
1560  return false;
1561  }
1562  }
1563  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
1564  /*AllowDestructorName*/ false,
1565  /*AllowConstructorName*/ false,
1566  /*AllowDeductionGuide*/ false,
1567  nullptr, TemplateKWLoc, ReductionId);
1568 }
1569 
1570 /// Parses clauses with list.
1572  OpenMPClauseKind Kind,
1574  OpenMPVarListDataTy &Data) {
1575  UnqualifiedId UnqualifiedReductionId;
1576  bool InvalidReductionId = false;
1577  bool MapTypeModifierSpecified = false;
1578 
1579  // Parse '('.
1580  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1581  if (T.expectAndConsume(diag::err_expected_lparen_after,
1582  getOpenMPClauseName(Kind)))
1583  return true;
1584 
1585  bool NeedRParenForLinear = false;
1586  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
1587  tok::annot_pragma_openmp_end);
1588  // Handle reduction-identifier for reduction clause.
1589  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) {
1590  ColonProtectionRAIIObject ColonRAII(*this);
1591  if (getLangOpts().CPlusPlus)
1592  ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
1593  /*ObjectType=*/nullptr,
1594  /*EnteringContext=*/false);
1595  InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
1596  UnqualifiedReductionId);
1597  if (InvalidReductionId) {
1598  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1599  StopBeforeMatch);
1600  }
1601  if (Tok.is(tok::colon))
1602  Data.ColonLoc = ConsumeToken();
1603  else
1604  Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
1605  if (!InvalidReductionId)
1606  Data.ReductionId =
1607  Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1608  } else if (Kind == OMPC_depend) {
1609  // Handle dependency type for depend clause.
1610  ColonProtectionRAIIObject ColonRAII(*this);
1611  Data.DepKind =
1613  Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
1614  Data.DepLinMapLoc = Tok.getLocation();
1615 
1616  if (Data.DepKind == OMPC_DEPEND_unknown) {
1617  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1618  StopBeforeMatch);
1619  } else {
1620  ConsumeToken();
1621  // Special processing for depend(source) clause.
1622  if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
1623  // Parse ')'.
1624  T.consumeClose();
1625  return false;
1626  }
1627  }
1628  if (Tok.is(tok::colon))
1629  Data.ColonLoc = ConsumeToken();
1630  else {
1631  Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1632  : diag::warn_pragma_expected_colon)
1633  << "dependency type";
1634  }
1635  } else if (Kind == OMPC_linear) {
1636  // Try to parse modifier if any.
1637  if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
1638  Data.LinKind = static_cast<OpenMPLinearClauseKind>(
1639  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
1640  Data.DepLinMapLoc = ConsumeToken();
1641  LinearT.consumeOpen();
1642  NeedRParenForLinear = true;
1643  }
1644  } else if (Kind == OMPC_map) {
1645  // Handle map type for map clause.
1646  ColonProtectionRAIIObject ColonRAII(*this);
1647 
1648  /// The map clause modifier token can be either a identifier or the C++
1649  /// delete keyword.
1650  auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
1651  return Tok.isOneOf(tok::identifier, tok::kw_delete);
1652  };
1653 
1654  // The first identifier may be a list item, a map-type or a
1655  // map-type-modifier. The map modifier can also be delete which has the same
1656  // spelling of the C++ delete keyword.
1657  Data.MapType =
1658  IsMapClauseModifierToken(Tok)
1659  ? static_cast<OpenMPMapClauseKind>(
1660  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1661  : OMPC_MAP_unknown;
1662  Data.DepLinMapLoc = Tok.getLocation();
1663  bool ColonExpected = false;
1664 
1665  if (IsMapClauseModifierToken(Tok)) {
1666  if (PP.LookAhead(0).is(tok::colon)) {
1667  if (Data.MapType == OMPC_MAP_unknown)
1668  Diag(Tok, diag::err_omp_unknown_map_type);
1669  else if (Data.MapType == OMPC_MAP_always)
1670  Diag(Tok, diag::err_omp_map_type_missing);
1671  ConsumeToken();
1672  } else if (PP.LookAhead(0).is(tok::comma)) {
1673  if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
1674  PP.LookAhead(2).is(tok::colon)) {
1675  Data.MapTypeModifier = Data.MapType;
1676  if (Data.MapTypeModifier != OMPC_MAP_always) {
1677  Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1679  } else
1680  MapTypeModifierSpecified = true;
1681 
1682  ConsumeToken();
1683  ConsumeToken();
1684 
1685  Data.MapType =
1686  IsMapClauseModifierToken(Tok)
1687  ? static_cast<OpenMPMapClauseKind>(
1688  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1689  : OMPC_MAP_unknown;
1690  if (Data.MapType == OMPC_MAP_unknown ||
1691  Data.MapType == OMPC_MAP_always)
1692  Diag(Tok, diag::err_omp_unknown_map_type);
1693  ConsumeToken();
1694  } else {
1695  Data.MapType = OMPC_MAP_tofrom;
1696  Data.IsMapTypeImplicit = true;
1697  }
1698  } else if (IsMapClauseModifierToken(PP.LookAhead(0))) {
1699  if (PP.LookAhead(1).is(tok::colon)) {
1700  Data.MapTypeModifier = Data.MapType;
1701  if (Data.MapTypeModifier != OMPC_MAP_always) {
1702  Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1704  } else
1705  MapTypeModifierSpecified = true;
1706 
1707  ConsumeToken();
1708 
1709  Data.MapType =
1710  IsMapClauseModifierToken(Tok)
1711  ? static_cast<OpenMPMapClauseKind>(
1712  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1713  : OMPC_MAP_unknown;
1714  if (Data.MapType == OMPC_MAP_unknown ||
1715  Data.MapType == OMPC_MAP_always)
1716  Diag(Tok, diag::err_omp_unknown_map_type);
1717  ConsumeToken();
1718  } else {
1719  Data.MapType = OMPC_MAP_tofrom;
1720  Data.IsMapTypeImplicit = true;
1721  }
1722  } else {
1723  Data.MapType = OMPC_MAP_tofrom;
1724  Data.IsMapTypeImplicit = true;
1725  }
1726  } else {
1727  Data.MapType = OMPC_MAP_tofrom;
1728  Data.IsMapTypeImplicit = true;
1729  }
1730 
1731  if (Tok.is(tok::colon))
1732  Data.ColonLoc = ConsumeToken();
1733  else if (ColonExpected)
1734  Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
1735  }
1736 
1737  bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
1738  Kind != OMPC_depend && Kind != OMPC_map) ||
1739  (Kind == OMPC_reduction && !InvalidReductionId) ||
1740  (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
1741  (!MapTypeModifierSpecified ||
1742  Data.MapTypeModifier == OMPC_MAP_always)) ||
1743  (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
1744  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1745  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
1746  Tok.isNot(tok::annot_pragma_openmp_end))) {
1747  ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
1748  // Parse variable
1749  ExprResult VarExpr =
1750  Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
1751  if (VarExpr.isUsable())
1752  Vars.push_back(VarExpr.get());
1753  else {
1754  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1755  StopBeforeMatch);
1756  }
1757  // Skip ',' if any
1758  IsComma = Tok.is(tok::comma);
1759  if (IsComma)
1760  ConsumeToken();
1761  else if (Tok.isNot(tok::r_paren) &&
1762  Tok.isNot(tok::annot_pragma_openmp_end) &&
1763  (!MayHaveTail || Tok.isNot(tok::colon)))
1764  Diag(Tok, diag::err_omp_expected_punc)
1765  << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
1766  : getOpenMPClauseName(Kind))
1767  << (Kind == OMPC_flush);
1768  }
1769 
1770  // Parse ')' for linear clause with modifier.
1771  if (NeedRParenForLinear)
1772  LinearT.consumeClose();
1773 
1774  // Parse ':' linear-step (or ':' alignment).
1775  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
1776  if (MustHaveTail) {
1777  Data.ColonLoc = Tok.getLocation();
1778  SourceLocation ELoc = ConsumeToken();
1780  Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
1781  if (Tail.isUsable())
1782  Data.TailExpr = Tail.get();
1783  else
1784  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1785  StopBeforeMatch);
1786  }
1787 
1788  // Parse ')'.
1789  T.consumeClose();
1790  if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
1791  Vars.empty()) ||
1792  (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1793  (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
1794  return true;
1795  return false;
1796 }
1797 
1798 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
1799 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'.
1800 ///
1801 /// private-clause:
1802 /// 'private' '(' list ')'
1803 /// firstprivate-clause:
1804 /// 'firstprivate' '(' list ')'
1805 /// lastprivate-clause:
1806 /// 'lastprivate' '(' list ')'
1807 /// shared-clause:
1808 /// 'shared' '(' list ')'
1809 /// linear-clause:
1810 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
1811 /// aligned-clause:
1812 /// 'aligned' '(' list [ ':' alignment ] ')'
1813 /// reduction-clause:
1814 /// 'reduction' '(' reduction-identifier ':' list ')'
1815 /// task_reduction-clause:
1816 /// 'task_reduction' '(' reduction-identifier ':' list ')'
1817 /// copyprivate-clause:
1818 /// 'copyprivate' '(' list ')'
1819 /// flush-clause:
1820 /// 'flush' '(' list ')'
1821 /// depend-clause:
1822 /// 'depend' '(' in | out | inout : list | source ')'
1823 /// map-clause:
1824 /// 'map' '(' [ [ always , ]
1825 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
1826 /// to-clause:
1827 /// 'to' '(' list ')'
1828 /// from-clause:
1829 /// 'from' '(' list ')'
1830 /// use_device_ptr-clause:
1831 /// 'use_device_ptr' '(' list ')'
1832 /// is_device_ptr-clause:
1833 /// 'is_device_ptr' '(' list ')'
1834 ///
1835 /// For 'linear' clause linear-list may have the following forms:
1836 /// list
1837 /// modifier(list)
1838 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
1839 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
1840  OpenMPClauseKind Kind) {
1841  SourceLocation Loc = Tok.getLocation();
1842  SourceLocation LOpen = ConsumeToken();
1844  OpenMPVarListDataTy Data;
1845 
1846  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
1847  return nullptr;
1848 
1849  return Actions.ActOnOpenMPVarListClause(
1850  Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
1851  Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1852  Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
1853  Data.DepLinMapLoc);
1854 }
1855 
OpenMPDependClauseKind DepKind
Definition: Parser.h:2682
SourceLocation getCloseLocation() const
Defines the clang::ASTContext interface.
ParseScope - Introduces a new scope for parsing.
Definition: Parser.h:840
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
bool isInvalid() const
Definition: Ownership.h:159
DeclarationNameInfo ReductionId
Definition: Parser.h:2681
DeclContext * getCurLexicalContext() const
Definition: Sema.h:10422
const Token & getCurToken() const
Definition: Parser.h:273
const LangOptions & getLangOpts() const
Definition: Parser.h:267
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
StringRef P
PtrTy get() const
Definition: Ownership.h:163
The base class of the type hierarchy.
Definition: Type.h:1303
This indicates that the scope corresponds to a function, which means that labels are set here...
Definition: Scope.h:46
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind)
static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P)
Definition: ParseOpenMP.cpp:83
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:94
void ActOnExitFunctionContext()
Definition: SemaDecl.cpp:1312
Wrapper for void* pointer.
Definition: Ownership.h:45
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:57
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
void EnterToken(const Token &Tok)
Enters a token in the token stream to be lexed next.
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:45
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
Definition: Token.h:107
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition: Sema.h:4980
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed...
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool isEmpty() const
No scope specifier.
Definition: DeclSpec.h:189
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:934
OpenMPLinearClauseKind LinKind
Definition: Parser.h:2683
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation >> ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:40
RecordDecl - Represents a struct/union/class.
Definition: Decl.h:3354
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
Definition: OpenMPKinds.cpp:62
One of these records is kept for each identifier that is lexed.
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition: OpenMPKinds.h:84
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
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.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
VerifyDiagnosticConsumer::Directive Directive
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:899
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer)
Finish current declare reduction construct initializer.
void ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult StmtError()
Definition: Ownership.h:269
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 'declare simd' directive.
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str)
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:63
tok::TokenKind getKind() const
Definition: Token.h:90
detail::InMemoryDirectory::const_iterator I
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition: DeclBase.h:980
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:269
A RAII object to enter scope of a compound statement.
Definition: Sema.h:3613
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:516
TypeResult ParseTypeName(SourceRange *Range=nullptr, Declarator::TheContext Context=Declarator::TypeNameContext, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)
ParseTypeName type-name: [C99 6.7.6] specifier-qualifier-list abstract-declarator[opt].
Definition: ParseDecl.cpp:45
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition: Decl.cpp:1674
OpenMPMapClauseKind MapTypeModifier
Definition: Parser.h:2684
StringRef getName() const
Return the actual identifier string.
bool isEmpty() const
Evaluates true when this declaration name is empty.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
MatchFinder::MatchCallback * Callback
bool isTemplateDecl() const
returns true if this declaration is a template
Definition: DeclBase.cpp:207
This is the scope of OpenMP executable directive.
Definition: Scope.h:106
OpenMPDirectiveKindEx
Definition: ParseOpenMP.cpp:29
OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:33
DeclContext * getDeclContext()
Definition: DeclBase.h:416
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:124
bool isNot(tok::TokenKind K) const
Definition: Token.h:96
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition: Parser.h:283
ExprResult ActOnFinishFullExpr(Expr *Expr)
Definition: Sema.h:5184
A class for parsing a DeclSpec.
Kind
Encodes a location in the source.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:76
SourceLocation getEndLoc() const
Definition: Token.h:151
bool isValid() const
Return true if this is a valid SourceLocation object.
ASTContext & getASTContext() const
Definition: Sema.h:1173
static unsigned getOpenMPDirectiveKindEx(StringRef S)
Definition: ParseOpenMP.cpp:65
OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:23
Scope * getCurScope() const
Definition: Parser.h:274
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:33
Preprocessor & getPreprocessor() const
Definition: Parser.h:269
SourceLocation getBegin() const
PtrTy get() const
Definition: Ownership.h:74
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:95
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
Sema & getActions() const
Definition: Parser.h:270
StringRef Name
Definition: USRFinder.cpp:123
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
Definition: Parser.cpp:2207
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:22
This is the scope of some OpenMP simd directive.
Definition: Scope.h:114
This is a scope that corresponds to the template parameters of a C++ template.
Definition: Scope.h:76
DeclarationName - The name of a declaration.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
Data used for parsing list of variables in OpenMP clauses.
Definition: Parser.h:2677
detail::InMemoryDirectory::const_iterator E
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
static const TST TST_unspecified
Definition: DeclSpec.h:272
Not an overloaded operator.
Definition: OperatorKinds.h:23
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
Definition: Token.h:97
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
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:1291
ActionResult< Stmt * > StmtResult
Definition: Ownership.h:253
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
Definition: ParseExpr.cpp:156
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str)
const char * getOpenMPDirectiveName(OpenMPDirectiveKind Kind)
Definition: OpenMPKinds.cpp:31
bool isUsable() const
Definition: Ownership.h:160
This is a scope that can contain a declaration.
Definition: Scope.h:58
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Definition: Parser.h:312
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:92
static DeclarationName parseOpenMPReductionId(Parser &P)
This is the scope of some OpenMP loop directive.
Definition: Scope.h:109
ExprResult ExprError()
Definition: Ownership.h:268
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, OpenMPVarListDataTy &Data)
Parses clauses with list.
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.
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
Directive - Abstract class representing a parsed verify directive.
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Definition: Token.h:118
OpenMPMapClauseKind MapType
Definition: Parser.h:2685
Stop skipping at specified token, but don't skip the token itself.
Definition: Parser.h:916
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177