clang  3.7.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 "RAIIObjectsForParser.h"
15 #include "clang/AST/ASTConsumer.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtOpenMP.h"
19 #include "clang/Parse/Parser.h"
20 #include "clang/Sema/Scope.h"
21 #include "llvm/ADT/PointerIntPair.h"
22 using namespace clang;
23 
24 //===----------------------------------------------------------------------===//
25 // OpenMP declarative directives.
26 //===----------------------------------------------------------------------===//
27 
29  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
30  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
31  // TODO: add other combined directives in topological order.
32  const OpenMPDirectiveKind F[][3] = {
33  {OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/,
34  OMPD_cancellation_point},
35  {OMPD_for, OMPD_simd, OMPD_for_simd},
36  {OMPD_parallel, OMPD_for, OMPD_parallel_for},
37  {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
38  {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}};
39  auto Tok = P.getCurToken();
40  auto DKind =
41  Tok.isAnnotation()
42  ? OMPD_unknown
44  bool TokenMatched = false;
45  for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
46  if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
47  TokenMatched =
48  (i == 0) &&
49  !P.getPreprocessor().getSpelling(Tok).compare("cancellation");
50  } else {
51  TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown;
52  }
53  if (TokenMatched) {
54  Tok = P.getPreprocessor().LookAhead(0);
55  auto SDKind =
56  Tok.isAnnotation()
57  ? OMPD_unknown
59  if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
60  TokenMatched =
61  (i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point");
62  } else {
63  TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown;
64  }
65  if (TokenMatched) {
66  P.ConsumeToken();
67  DKind = F[i][2];
68  }
69  }
70  }
71  return DKind;
72 }
73 
74 /// \brief Parsing of declarative OpenMP directives.
75 ///
76 /// threadprivate-directive:
77 /// annot_pragma_openmp 'threadprivate' simple-variable-list
78 ///
79 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
80  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
81  ParenBraceBracketBalancer BalancerRAIIObj(*this);
82 
84  SmallVector<Expr *, 5> Identifiers;
85  auto DKind = ParseOpenMPDirectiveKind(*this);
86 
87  switch (DKind) {
88  case OMPD_threadprivate:
89  ConsumeToken();
90  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
91  // The last seen token is annot_pragma_openmp_end - need to check for
92  // extra tokens.
93  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
94  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
95  << getOpenMPDirectiveName(OMPD_threadprivate);
96  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
97  }
98  // Skip the last annot_pragma_openmp_end.
99  ConsumeToken();
100  return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
101  }
102  break;
103  case OMPD_unknown:
104  Diag(Tok, diag::err_omp_unknown_directive);
105  break;
106  case OMPD_parallel:
107  case OMPD_simd:
108  case OMPD_task:
109  case OMPD_taskyield:
110  case OMPD_barrier:
111  case OMPD_taskwait:
112  case OMPD_taskgroup:
113  case OMPD_flush:
114  case OMPD_for:
115  case OMPD_for_simd:
116  case OMPD_sections:
117  case OMPD_section:
118  case OMPD_single:
119  case OMPD_master:
120  case OMPD_ordered:
121  case OMPD_critical:
122  case OMPD_parallel_for:
123  case OMPD_parallel_for_simd:
124  case OMPD_parallel_sections:
125  case OMPD_atomic:
126  case OMPD_target:
127  case OMPD_teams:
128  case OMPD_cancellation_point:
129  case OMPD_cancel:
130  Diag(Tok, diag::err_omp_unexpected_directive)
131  << getOpenMPDirectiveName(DKind);
132  break;
133  }
134  SkipUntil(tok::annot_pragma_openmp_end);
135  return DeclGroupPtrTy();
136 }
137 
138 /// \brief Parsing of declarative or executable OpenMP directives.
139 ///
140 /// threadprivate-directive:
141 /// annot_pragma_openmp 'threadprivate' simple-variable-list
142 /// annot_pragma_openmp_end
143 ///
144 /// executable-directive:
145 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
146 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
147 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
148 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
149 /// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup'
150 /// {clause}
151 /// annot_pragma_openmp_end
152 ///
154 Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
155  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
156  ParenBraceBracketBalancer BalancerRAIIObj(*this);
157  SmallVector<Expr *, 5> Identifiers;
160  FirstClauses(OMPC_unknown + 1);
161  unsigned ScopeFlags =
163  SourceLocation Loc = ConsumeToken(), EndLoc;
164  auto DKind = ParseOpenMPDirectiveKind(*this);
165  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
166  // Name of critical directive.
167  DeclarationNameInfo DirName;
169  bool HasAssociatedStatement = true;
170  bool FlushHasClause = false;
171 
172  switch (DKind) {
173  case OMPD_threadprivate:
174  ConsumeToken();
175  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
176  // The last seen token is annot_pragma_openmp_end - need to check for
177  // extra tokens.
178  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
179  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
180  << getOpenMPDirectiveName(OMPD_threadprivate);
181  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
182  }
183  DeclGroupPtrTy Res =
184  Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
185  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
186  }
187  SkipUntil(tok::annot_pragma_openmp_end);
188  break;
189  case OMPD_flush:
190  if (PP.LookAhead(0).is(tok::l_paren)) {
191  FlushHasClause = true;
192  // Push copy of the current token back to stream to properly parse
193  // pseudo-clause OMPFlushClause.
194  PP.EnterToken(Tok);
195  }
196  case OMPD_taskyield:
197  case OMPD_barrier:
198  case OMPD_taskwait:
199  case OMPD_cancellation_point:
200  case OMPD_cancel:
201  if (!StandAloneAllowed) {
202  Diag(Tok, diag::err_omp_immediate_directive)
203  << getOpenMPDirectiveName(DKind);
204  }
205  HasAssociatedStatement = false;
206  // Fall through for further analysis.
207  case OMPD_parallel:
208  case OMPD_simd:
209  case OMPD_for:
210  case OMPD_for_simd:
211  case OMPD_sections:
212  case OMPD_single:
213  case OMPD_section:
214  case OMPD_master:
215  case OMPD_critical:
216  case OMPD_parallel_for:
217  case OMPD_parallel_for_simd:
218  case OMPD_parallel_sections:
219  case OMPD_task:
220  case OMPD_ordered:
221  case OMPD_atomic:
222  case OMPD_target:
223  case OMPD_teams:
224  case OMPD_taskgroup: {
225  ConsumeToken();
226  // Parse directive name of the 'critical' directive if any.
227  if (DKind == OMPD_critical) {
228  BalancedDelimiterTracker T(*this, tok::l_paren,
229  tok::annot_pragma_openmp_end);
230  if (!T.consumeOpen()) {
231  if (Tok.isAnyIdentifier()) {
232  DirName =
234  ConsumeAnyToken();
235  } else {
236  Diag(Tok, diag::err_omp_expected_identifier_for_critical);
237  }
238  T.consumeClose();
239  }
240  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
241  CancelRegion = ParseOpenMPDirectiveKind(*this);
242  if (Tok.isNot(tok::annot_pragma_openmp_end))
243  ConsumeToken();
244  }
245 
246  if (isOpenMPLoopDirective(DKind))
247  ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
248  if (isOpenMPSimdDirective(DKind))
249  ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
250  ParseScope OMPDirectiveScope(this, ScopeFlags);
251  Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
252 
253  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
254  OpenMPClauseKind CKind =
255  Tok.isAnnotation()
256  ? OMPC_unknown
257  : FlushHasClause ? OMPC_flush
258  : getOpenMPClauseKind(PP.getSpelling(Tok));
259  Actions.StartOpenMPClause(CKind);
260  FlushHasClause = false;
261  OMPClause *Clause =
262  ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
263  FirstClauses[CKind].setInt(true);
264  if (Clause) {
265  FirstClauses[CKind].setPointer(Clause);
266  Clauses.push_back(Clause);
267  }
268 
269  // Skip ',' if any.
270  if (Tok.is(tok::comma))
271  ConsumeToken();
272  Actions.EndOpenMPClause();
273  }
274  // End location of the directive.
275  EndLoc = Tok.getLocation();
276  // Consume final annot_pragma_openmp_end.
277  ConsumeToken();
278 
279  StmtResult AssociatedStmt;
280  bool CreateDirective = true;
281  if (HasAssociatedStatement) {
282  // The body is a block scope like in Lambdas and Blocks.
283  Sema::CompoundScopeRAII CompoundScope(Actions);
284  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
285  Actions.ActOnStartOfCompoundStmt();
286  // Parse statement
287  AssociatedStmt = ParseStatement();
288  Actions.ActOnFinishOfCompoundStmt();
289  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
290  CreateDirective = AssociatedStmt.isUsable();
291  }
292  if (CreateDirective)
293  Directive = Actions.ActOnOpenMPExecutableDirective(
294  DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
295  EndLoc);
296 
297  // Exit scope.
298  Actions.EndOpenMPDSABlock(Directive.get());
299  OMPDirectiveScope.Exit();
300  break;
301  }
302  case OMPD_unknown:
303  Diag(Tok, diag::err_omp_unknown_directive);
304  SkipUntil(tok::annot_pragma_openmp_end);
305  break;
306  }
307  return Directive;
308 }
309 
310 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
311 /// directive.
312 ///
313 /// simple-variable-list:
314 /// '(' id-expression {, id-expression} ')'
315 ///
316 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
317  SmallVectorImpl<Expr *> &VarList,
318  bool AllowScopeSpecifier) {
319  VarList.clear();
320  // Parse '('.
321  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
322  if (T.expectAndConsume(diag::err_expected_lparen_after,
323  getOpenMPDirectiveName(Kind)))
324  return true;
325  bool IsCorrect = true;
326  bool NoIdentIsFound = true;
327 
328  // Read tokens while ')' or annot_pragma_openmp_end is not found.
329  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
330  CXXScopeSpec SS;
331  SourceLocation TemplateKWLoc;
332  UnqualifiedId Name;
333  // Read var name.
334  Token PrevTok = Tok;
335  NoIdentIsFound = false;
336 
337  if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
338  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
339  IsCorrect = false;
340  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
342  } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
343  TemplateKWLoc, Name)) {
344  IsCorrect = false;
345  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
347  } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
348  Tok.isNot(tok::annot_pragma_openmp_end)) {
349  IsCorrect = false;
350  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
352  Diag(PrevTok.getLocation(), diag::err_expected)
353  << tok::identifier
354  << SourceRange(PrevTok.getLocation(), PrevTokLocation);
355  } else {
356  DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
357  ExprResult Res =
358  Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
359  if (Res.isUsable())
360  VarList.push_back(Res.get());
361  }
362  // Consume ','.
363  if (Tok.is(tok::comma)) {
364  ConsumeToken();
365  }
366  }
367 
368  if (NoIdentIsFound) {
369  Diag(Tok, diag::err_expected) << tok::identifier;
370  IsCorrect = false;
371  }
372 
373  // Parse ')'.
374  IsCorrect = !T.consumeClose() && IsCorrect;
375 
376  return !IsCorrect && VarList.empty();
377 }
378 
379 /// \brief Parsing of OpenMP clauses.
380 ///
381 /// clause:
382 /// if-clause | final-clause | num_threads-clause | safelen-clause |
383 /// default-clause | private-clause | firstprivate-clause | shared-clause
384 /// | linear-clause | aligned-clause | collapse-clause |
385 /// lastprivate-clause | reduction-clause | proc_bind-clause |
386 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
387 /// mergeable-clause | flush-clause | read-clause | write-clause |
388 /// update-clause | capture-clause | seq_cst-clause
389 ///
390 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
391  OpenMPClauseKind CKind, bool FirstClause) {
392  OMPClause *Clause = nullptr;
393  bool ErrorFound = false;
394  // Check if clause is allowed for the given directive.
395  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
396  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
397  << getOpenMPDirectiveName(DKind);
398  ErrorFound = true;
399  }
400 
401  switch (CKind) {
402  case OMPC_if:
403  case OMPC_final:
404  case OMPC_num_threads:
405  case OMPC_safelen:
406  case OMPC_collapse:
407  // OpenMP [2.5, Restrictions]
408  // At most one if clause can appear on the directive.
409  // At most one num_threads clause can appear on the directive.
410  // OpenMP [2.8.1, simd construct, Restrictions]
411  // Only one safelen clause can appear on a simd directive.
412  // Only one collapse clause can appear on a simd directive.
413  // OpenMP [2.11.1, task Construct, Restrictions]
414  // At most one if clause can appear on the directive.
415  // At most one final clause can appear on the directive.
416  if (!FirstClause) {
417  Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
418  << getOpenMPClauseName(CKind);
419  ErrorFound = true;
420  }
421 
422  Clause = ParseOpenMPSingleExprClause(CKind);
423  break;
424  case OMPC_default:
425  case OMPC_proc_bind:
426  // OpenMP [2.14.3.1, Restrictions]
427  // Only a single default clause may be specified on a parallel, task or
428  // teams directive.
429  // OpenMP [2.5, parallel Construct, Restrictions]
430  // At most one proc_bind clause can appear on the directive.
431  if (!FirstClause) {
432  Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
433  << getOpenMPClauseName(CKind);
434  ErrorFound = true;
435  }
436 
437  Clause = ParseOpenMPSimpleClause(CKind);
438  break;
439  case OMPC_schedule:
440  // OpenMP [2.7.1, Restrictions, p. 3]
441  // Only one schedule clause can appear on a loop directive.
442  if (!FirstClause) {
443  Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
444  << getOpenMPClauseName(CKind);
445  ErrorFound = true;
446  }
447 
448  Clause = ParseOpenMPSingleExprWithArgClause(CKind);
449  break;
450  case OMPC_ordered:
451  case OMPC_nowait:
452  case OMPC_untied:
453  case OMPC_mergeable:
454  case OMPC_read:
455  case OMPC_write:
456  case OMPC_update:
457  case OMPC_capture:
458  case OMPC_seq_cst:
459  // OpenMP [2.7.1, Restrictions, p. 9]
460  // Only one ordered clause can appear on a loop directive.
461  // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
462  // Only one nowait clause can appear on a for directive.
463  if (!FirstClause) {
464  Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
465  << getOpenMPClauseName(CKind);
466  ErrorFound = true;
467  }
468 
469  Clause = ParseOpenMPClause(CKind);
470  break;
471  case OMPC_private:
472  case OMPC_firstprivate:
473  case OMPC_lastprivate:
474  case OMPC_shared:
475  case OMPC_reduction:
476  case OMPC_linear:
477  case OMPC_aligned:
478  case OMPC_copyin:
479  case OMPC_copyprivate:
480  case OMPC_flush:
481  case OMPC_depend:
482  Clause = ParseOpenMPVarListClause(CKind);
483  break;
484  case OMPC_unknown:
485  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
486  << getOpenMPDirectiveName(DKind);
487  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
488  break;
489  case OMPC_threadprivate:
490  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
491  << getOpenMPDirectiveName(DKind);
492  SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
493  break;
494  }
495  return ErrorFound ? nullptr : Clause;
496 }
497 
498 /// \brief Parsing of OpenMP clauses with single expressions like 'if',
499 /// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
500 /// 'thread_limit'.
501 ///
502 /// if-clause:
503 /// 'if' '(' expression ')'
504 ///
505 /// final-clause:
506 /// 'final' '(' expression ')'
507 ///
508 /// num_threads-clause:
509 /// 'num_threads' '(' expression ')'
510 ///
511 /// safelen-clause:
512 /// 'safelen' '(' expression ')'
513 ///
514 /// collapse-clause:
515 /// 'collapse' '(' expression ')'
516 ///
517 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
519 
520  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
521  if (T.expectAndConsume(diag::err_expected_lparen_after,
522  getOpenMPClauseName(Kind)))
523  return nullptr;
524 
525  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
526  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
527 
528  // Parse ')'.
529  T.consumeClose();
530 
531  if (Val.isInvalid())
532  return nullptr;
533 
534  return Actions.ActOnOpenMPSingleExprClause(
535  Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
536 }
537 
538 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
539 ///
540 /// default-clause:
541 /// 'default' '(' 'none' | 'shared' ')
542 ///
543 /// proc_bind-clause:
544 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
545 ///
546 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
547  SourceLocation Loc = Tok.getLocation();
548  SourceLocation LOpen = ConsumeToken();
549  // Parse '('.
550  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
551  if (T.expectAndConsume(diag::err_expected_lparen_after,
552  getOpenMPClauseName(Kind)))
553  return nullptr;
554 
555  unsigned Type = getOpenMPSimpleClauseType(
556  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
558  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
559  Tok.isNot(tok::annot_pragma_openmp_end))
560  ConsumeAnyToken();
561 
562  // Parse ')'.
563  T.consumeClose();
564 
565  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
566  Tok.getLocation());
567 }
568 
569 /// \brief Parsing of OpenMP clauses like 'ordered'.
570 ///
571 /// ordered-clause:
572 /// 'ordered'
573 ///
574 /// nowait-clause:
575 /// 'nowait'
576 ///
577 /// untied-clause:
578 /// 'untied'
579 ///
580 /// mergeable-clause:
581 /// 'mergeable'
582 ///
583 /// read-clause:
584 /// 'read'
585 ///
586 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
587  SourceLocation Loc = Tok.getLocation();
588  ConsumeAnyToken();
589 
590  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
591 }
592 
593 
594 /// \brief Parsing of OpenMP clauses with single expressions and some additional
595 /// argument like 'schedule' or 'dist_schedule'.
596 ///
597 /// schedule-clause:
598 /// 'schedule' '(' kind [',' expression ] ')'
599 ///
600 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
602  SourceLocation CommaLoc;
603  // Parse '('.
604  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
605  if (T.expectAndConsume(diag::err_expected_lparen_after,
606  getOpenMPClauseName(Kind)))
607  return nullptr;
608 
609  ExprResult Val;
610  unsigned Type = getOpenMPSimpleClauseType(
611  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
612  SourceLocation KLoc = Tok.getLocation();
613  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
614  Tok.isNot(tok::annot_pragma_openmp_end))
615  ConsumeAnyToken();
616 
617  if (Kind == OMPC_schedule &&
618  (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
619  Type == OMPC_SCHEDULE_guided) &&
620  Tok.is(tok::comma)) {
621  CommaLoc = ConsumeAnyToken();
622  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
623  Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
624  if (Val.isInvalid())
625  return nullptr;
626  }
627 
628  // Parse ')'.
629  T.consumeClose();
630 
631  return Actions.ActOnOpenMPSingleExprWithArgClause(
632  Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
633  T.getCloseLocation());
634 }
635 
636 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
637  UnqualifiedId &ReductionId) {
638  SourceLocation TemplateKWLoc;
639  if (ReductionIdScopeSpec.isEmpty()) {
640  auto OOK = OO_None;
641  switch (P.getCurToken().getKind()) {
642  case tok::plus:
643  OOK = OO_Plus;
644  break;
645  case tok::minus:
646  OOK = OO_Minus;
647  break;
648  case tok::star:
649  OOK = OO_Star;
650  break;
651  case tok::amp:
652  OOK = OO_Amp;
653  break;
654  case tok::pipe:
655  OOK = OO_Pipe;
656  break;
657  case tok::caret:
658  OOK = OO_Caret;
659  break;
660  case tok::ampamp:
661  OOK = OO_AmpAmp;
662  break;
663  case tok::pipepipe:
664  OOK = OO_PipePipe;
665  break;
666  default:
667  break;
668  }
669  if (OOK != OO_None) {
670  SourceLocation OpLoc = P.ConsumeToken();
671  SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
672  ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
673  return false;
674  }
675  }
676  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
677  /*AllowDestructorName*/ false,
678  /*AllowConstructorName*/ false, ParsedType(),
679  TemplateKWLoc, ReductionId);
680 }
681 
682 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
683 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
684 ///
685 /// private-clause:
686 /// 'private' '(' list ')'
687 /// firstprivate-clause:
688 /// 'firstprivate' '(' list ')'
689 /// lastprivate-clause:
690 /// 'lastprivate' '(' list ')'
691 /// shared-clause:
692 /// 'shared' '(' list ')'
693 /// linear-clause:
694 /// 'linear' '(' list [ ':' linear-step ] ')'
695 /// aligned-clause:
696 /// 'aligned' '(' list [ ':' alignment ] ')'
697 /// reduction-clause:
698 /// 'reduction' '(' reduction-identifier ':' list ')'
699 /// copyprivate-clause:
700 /// 'copyprivate' '(' list ')'
701 /// flush-clause:
702 /// 'flush' '(' list ')'
703 /// depend-clause:
704 /// 'depend' '(' in | out | inout : list ')'
705 ///
706 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
707  SourceLocation Loc = Tok.getLocation();
708  SourceLocation LOpen = ConsumeToken();
710  // Optional scope specifier and unqualified id for reduction identifier.
711  CXXScopeSpec ReductionIdScopeSpec;
712  UnqualifiedId ReductionId;
713  bool InvalidReductionId = false;
715  SourceLocation DepLoc;
716 
717  // Parse '('.
718  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
719  if (T.expectAndConsume(diag::err_expected_lparen_after,
720  getOpenMPClauseName(Kind)))
721  return nullptr;
722 
723  // Handle reduction-identifier for reduction clause.
724  if (Kind == OMPC_reduction) {
725  ColonProtectionRAIIObject ColonRAII(*this);
726  if (getLangOpts().CPlusPlus) {
727  ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
728  }
729  InvalidReductionId =
730  ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
731  if (InvalidReductionId) {
732  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
734  }
735  if (Tok.is(tok::colon)) {
736  ColonLoc = ConsumeToken();
737  } else {
738  Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
739  }
740  } else if (Kind == OMPC_depend) {
741  // Handle dependency type for depend clause.
742  ColonProtectionRAIIObject ColonRAII(*this);
743  DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
744  Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
745  DepLoc = Tok.getLocation();
746 
747  if (DepKind == OMPC_DEPEND_unknown) {
748  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
750  } else {
751  ConsumeToken();
752  }
753  if (Tok.is(tok::colon)) {
754  ColonLoc = ConsumeToken();
755  } else {
756  Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
757  }
758  }
759 
761  bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
762  ((Kind == OMPC_reduction) && !InvalidReductionId) ||
763  ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
764  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
765  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
766  Tok.isNot(tok::annot_pragma_openmp_end))) {
767  ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
768  // Parse variable
769  ExprResult VarExpr =
771  if (VarExpr.isUsable()) {
772  Vars.push_back(VarExpr.get());
773  } else {
774  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
776  }
777  // Skip ',' if any
778  IsComma = Tok.is(tok::comma);
779  if (IsComma)
780  ConsumeToken();
781  else if (Tok.isNot(tok::r_paren) &&
782  Tok.isNot(tok::annot_pragma_openmp_end) &&
783  (!MayHaveTail || Tok.isNot(tok::colon)))
784  Diag(Tok, diag::err_omp_expected_punc)
785  << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
786  : getOpenMPClauseName(Kind))
787  << (Kind == OMPC_flush);
788  }
789 
790  // Parse ':' linear-step (or ':' alignment).
791  Expr *TailExpr = nullptr;
792  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
793  if (MustHaveTail) {
794  ColonLoc = Tok.getLocation();
795  ConsumeToken();
796  ExprResult Tail =
798  if (Tail.isUsable())
799  TailExpr = Tail.get();
800  else
801  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
803  }
804 
805  // Parse ')'.
806  T.consumeClose();
807  if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
808  (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
809  InvalidReductionId)
810  return nullptr;
811 
812  return Actions.ActOnOpenMPVarListClause(
813  Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
814  ReductionIdScopeSpec,
815  ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
817  DepKind, DepLoc);
818 }
819 
Defines the clang::ASTContext interface.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Called on correct id-expression from the '#pragma omp threadprivate'.
Definition: SemaOpenMP.cpp:777
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:8979
bool isInvalid() const
Definition: Ownership.h:159
const Token & getCurToken() const
Definition: Parse/Parser.h:249
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
Definition: SemaOpenMP.cpp:702
const LangOptions & getLangOpts() const
Definition: Parse/Parser.h:243
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
PtrTy get() const
Definition: Ownership.h:163
This indicates that the scope corresponds to a function, which means that labels are set here...
Definition: Scope.h:45
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind)
static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P)
Definition: ParseOpenMP.cpp:28
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
Wrapper for void* pointer.
Definition: Ownership.h:45
void EnterToken(const Token &Tok)
Enters a token in the token stream to be lexed next.
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 that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
bool isEmpty() const
No scope specifier.
Definition: DeclSpec.h:194
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
Definition: Parse/Parser.h:861
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:40
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
Definition: OpenMPKinds.cpp:61
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)
Retrieves the declaration name from a parsed unqualified-id.
Definition: SemaDecl.cpp:4363
OpaquePtr< QualType > ParsedType
Definition: Ownership.h:233
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
Definition: SemaOpenMP.cpp:687
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
void EndOpenMPClause()
End analysis of clauses.
Definition: SemaOpenMP.cpp:698
VerifyDiagnosticConsumer::Directive Directive
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:869
StmtResult StmtError()
Definition: Ownership.h:268
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str)
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:68
tok::TokenKind getKind() const
Definition: Token.h:90
AnnotatingParser & P
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:71
A RAII object to enter scope of a compound statement.
Definition: Sema.h:3222
void ActOnFinishOfCompoundStmt()
Definition: SemaStmt.cpp:314
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
Definition: SemaOpenMP.cpp:694
This is the scope of OpenMP executable directive.
Definition: Scope.h:105
OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:33
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: Parse/Parser.h:259
bool isValid() const
Determine whether this unqualified-id refers to a valid name.
Definition: DeclSpec.h:960
void ActOnStartOfCompoundStmt()
Definition: SemaStmt.cpp:310
Kind
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:66
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:23
Scope * getCurScope() const
Definition: Parse/Parser.h:250
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:32
Preprocessor & getPreprocessor() const
Definition: Parse/Parser.h:245
bool is(tok::TokenKind K) const
Definition: Token.h:95
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, ParsedType ObjectType, SourceLocation &TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
This is the scope of some OpenMP simd directive. For example, it is used for 'omp simd'...
Definition: Scope.h:113
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, unsigned Argument, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ArgumentLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Not an overloaded operator.
Definition: OperatorKinds.h:23
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
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:1215
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
Definition: ParseExpr.cpp:157
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
Definition: SemaOpenMP.cpp:902
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. Some scopes just contain loop constructs but don't co...
Definition: Scope.h:57
SourceLocation ConsumeToken()
Definition: Parse/Parser.h:284
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult{return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
This is the scope of some OpenMP loop directive.
Definition: Scope.h:108
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, Expr *TailExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind, SourceLocation DepLoc)
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.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
SourceLocation ColonLoc
Location of ':'.
Definition: OpenMPClause.h:260
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Definition: Token.h:118
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Stop skipping at specified token, but don't skip the token itself.
Definition: Parse/Parser.h:843
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177