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"
18 #include "clang/Parse/ParseDiagnostic.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 
ParseOpenMPDirectiveKind(Parser & P)28 static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
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_for, OMPD_simd, OMPD_for_simd },
34     { OMPD_parallel, OMPD_for, OMPD_parallel_for },
35     { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
36     { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }
37   };
38   auto Tok = P.getCurToken();
39   auto DKind =
40       Tok.isAnnotation()
41           ? OMPD_unknown
42           : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
43   for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
44     if (DKind == F[i][0]) {
45       Tok = P.getPreprocessor().LookAhead(0);
46       auto SDKind =
47           Tok.isAnnotation()
48               ? OMPD_unknown
49               : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
50       if (SDKind == F[i][1]) {
51         P.ConsumeToken();
52         DKind = F[i][2];
53       }
54     }
55   }
56   return DKind;
57 }
58 
59 /// \brief Parsing of declarative OpenMP directives.
60 ///
61 ///       threadprivate-directive:
62 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
63 ///
ParseOpenMPDeclarativeDirective()64 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
65   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
66   ParenBraceBracketBalancer BalancerRAIIObj(*this);
67 
68   SourceLocation Loc = ConsumeToken();
69   SmallVector<Expr *, 5> Identifiers;
70   auto DKind = ParseOpenMPDirectiveKind(*this);
71 
72   switch (DKind) {
73   case OMPD_threadprivate:
74     ConsumeToken();
75     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
76       // The last seen token is annot_pragma_openmp_end - need to check for
77       // extra tokens.
78       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
79         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
80             << getOpenMPDirectiveName(OMPD_threadprivate);
81         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
82       }
83       // Skip the last annot_pragma_openmp_end.
84       ConsumeToken();
85       return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
86     }
87     break;
88   case OMPD_unknown:
89     Diag(Tok, diag::err_omp_unknown_directive);
90     break;
91   case OMPD_parallel:
92   case OMPD_simd:
93   case OMPD_task:
94   case OMPD_taskyield:
95   case OMPD_barrier:
96   case OMPD_taskwait:
97   case OMPD_flush:
98   case OMPD_for:
99   case OMPD_for_simd:
100   case OMPD_sections:
101   case OMPD_section:
102   case OMPD_single:
103   case OMPD_master:
104   case OMPD_ordered:
105   case OMPD_critical:
106   case OMPD_parallel_for:
107   case OMPD_parallel_for_simd:
108   case OMPD_parallel_sections:
109   case OMPD_atomic:
110   case OMPD_target:
111   case OMPD_teams:
112     Diag(Tok, diag::err_omp_unexpected_directive)
113         << getOpenMPDirectiveName(DKind);
114     break;
115   }
116   SkipUntil(tok::annot_pragma_openmp_end);
117   return DeclGroupPtrTy();
118 }
119 
120 /// \brief Parsing of declarative or executable OpenMP directives.
121 ///
122 ///       threadprivate-directive:
123 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
124 ///         annot_pragma_openmp_end
125 ///
126 ///       executable-directive:
127 ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
128 ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
129 ///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
130 ///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
131 ///         'for simd' | 'parallel for simd' | 'target' | 'teams' {clause}
132 ///         annot_pragma_openmp_end
133 ///
134 StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed)135 Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
136   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
137   ParenBraceBracketBalancer BalancerRAIIObj(*this);
138   SmallVector<Expr *, 5> Identifiers;
139   SmallVector<OMPClause *, 5> Clauses;
140   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
141   FirstClauses(OMPC_unknown + 1);
142   unsigned ScopeFlags =
143       Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
144   SourceLocation Loc = ConsumeToken(), EndLoc;
145   auto DKind = ParseOpenMPDirectiveKind(*this);
146   // Name of critical directive.
147   DeclarationNameInfo DirName;
148   StmtResult Directive = StmtError();
149   bool HasAssociatedStatement = true;
150   bool FlushHasClause = false;
151 
152   switch (DKind) {
153   case OMPD_threadprivate:
154     ConsumeToken();
155     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
156       // The last seen token is annot_pragma_openmp_end - need to check for
157       // extra tokens.
158       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
159         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
160             << getOpenMPDirectiveName(OMPD_threadprivate);
161         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
162       }
163       DeclGroupPtrTy Res =
164           Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
165       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
166     }
167     SkipUntil(tok::annot_pragma_openmp_end);
168     break;
169   case OMPD_flush:
170     if (PP.LookAhead(0).is(tok::l_paren)) {
171       FlushHasClause = true;
172       // Push copy of the current token back to stream to properly parse
173       // pseudo-clause OMPFlushClause.
174       PP.EnterToken(Tok);
175     }
176   case OMPD_taskyield:
177   case OMPD_barrier:
178   case OMPD_taskwait:
179     if (!StandAloneAllowed) {
180       Diag(Tok, diag::err_omp_immediate_directive)
181           << getOpenMPDirectiveName(DKind);
182     }
183     HasAssociatedStatement = false;
184     // Fall through for further analysis.
185   case OMPD_parallel:
186   case OMPD_simd:
187   case OMPD_for:
188   case OMPD_for_simd:
189   case OMPD_sections:
190   case OMPD_single:
191   case OMPD_section:
192   case OMPD_master:
193   case OMPD_critical:
194   case OMPD_parallel_for:
195   case OMPD_parallel_for_simd:
196   case OMPD_parallel_sections:
197   case OMPD_task:
198   case OMPD_ordered:
199   case OMPD_atomic:
200   case OMPD_target:
201   case OMPD_teams: {
202     ConsumeToken();
203     // Parse directive name of the 'critical' directive if any.
204     if (DKind == OMPD_critical) {
205       BalancedDelimiterTracker T(*this, tok::l_paren,
206                                  tok::annot_pragma_openmp_end);
207       if (!T.consumeOpen()) {
208         if (Tok.isAnyIdentifier()) {
209           DirName =
210               DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
211           ConsumeAnyToken();
212         } else {
213           Diag(Tok, diag::err_omp_expected_identifier_for_critical);
214         }
215         T.consumeClose();
216       }
217     }
218 
219     if (isOpenMPLoopDirective(DKind))
220       ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
221     if (isOpenMPSimdDirective(DKind))
222       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
223     ParseScope OMPDirectiveScope(this, ScopeFlags);
224     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
225 
226     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
227       OpenMPClauseKind CKind =
228           Tok.isAnnotation()
229               ? OMPC_unknown
230               : FlushHasClause ? OMPC_flush
231                                : getOpenMPClauseKind(PP.getSpelling(Tok));
232       FlushHasClause = false;
233       OMPClause *Clause =
234           ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
235       FirstClauses[CKind].setInt(true);
236       if (Clause) {
237         FirstClauses[CKind].setPointer(Clause);
238         Clauses.push_back(Clause);
239       }
240 
241       // Skip ',' if any.
242       if (Tok.is(tok::comma))
243         ConsumeToken();
244     }
245     // End location of the directive.
246     EndLoc = Tok.getLocation();
247     // Consume final annot_pragma_openmp_end.
248     ConsumeToken();
249 
250     StmtResult AssociatedStmt;
251     bool CreateDirective = true;
252     if (HasAssociatedStatement) {
253       // The body is a block scope like in Lambdas and Blocks.
254       Sema::CompoundScopeRAII CompoundScope(Actions);
255       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
256       Actions.ActOnStartOfCompoundStmt();
257       // Parse statement
258       AssociatedStmt = ParseStatement();
259       Actions.ActOnFinishOfCompoundStmt();
260       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
261       CreateDirective = AssociatedStmt.isUsable();
262     }
263     if (CreateDirective)
264       Directive = Actions.ActOnOpenMPExecutableDirective(
265           DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
266 
267     // Exit scope.
268     Actions.EndOpenMPDSABlock(Directive.get());
269     OMPDirectiveScope.Exit();
270     break;
271   }
272   case OMPD_unknown:
273     Diag(Tok, diag::err_omp_unknown_directive);
274     SkipUntil(tok::annot_pragma_openmp_end);
275     break;
276   }
277   return Directive;
278 }
279 
280 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
281 /// directive.
282 ///
283 ///   simple-variable-list:
284 ///         '(' id-expression {, id-expression} ')'
285 ///
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,SmallVectorImpl<Expr * > & VarList,bool AllowScopeSpecifier)286 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
287                                       SmallVectorImpl<Expr *> &VarList,
288                                       bool AllowScopeSpecifier) {
289   VarList.clear();
290   // Parse '('.
291   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
292   if (T.expectAndConsume(diag::err_expected_lparen_after,
293                          getOpenMPDirectiveName(Kind)))
294     return true;
295   bool IsCorrect = true;
296   bool NoIdentIsFound = true;
297 
298   // Read tokens while ')' or annot_pragma_openmp_end is not found.
299   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
300     CXXScopeSpec SS;
301     SourceLocation TemplateKWLoc;
302     UnqualifiedId Name;
303     // Read var name.
304     Token PrevTok = Tok;
305     NoIdentIsFound = false;
306 
307     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
308         ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
309       IsCorrect = false;
310       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
311                 StopBeforeMatch);
312     } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
313                                   TemplateKWLoc, Name)) {
314       IsCorrect = false;
315       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
316                 StopBeforeMatch);
317     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
318                Tok.isNot(tok::annot_pragma_openmp_end)) {
319       IsCorrect = false;
320       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
321                 StopBeforeMatch);
322       Diag(PrevTok.getLocation(), diag::err_expected)
323           << tok::identifier
324           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
325     } else {
326       DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
327       ExprResult Res =
328           Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
329       if (Res.isUsable())
330         VarList.push_back(Res.get());
331     }
332     // Consume ','.
333     if (Tok.is(tok::comma)) {
334       ConsumeToken();
335     }
336   }
337 
338   if (NoIdentIsFound) {
339     Diag(Tok, diag::err_expected) << tok::identifier;
340     IsCorrect = false;
341   }
342 
343   // Parse ')'.
344   IsCorrect = !T.consumeClose() && IsCorrect;
345 
346   return !IsCorrect && VarList.empty();
347 }
348 
349 /// \brief Parsing of OpenMP clauses.
350 ///
351 ///    clause:
352 ///       if-clause | final-clause | num_threads-clause | safelen-clause |
353 ///       default-clause | private-clause | firstprivate-clause | shared-clause
354 ///       | linear-clause | aligned-clause | collapse-clause |
355 ///       lastprivate-clause | reduction-clause | proc_bind-clause |
356 ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
357 ///       mergeable-clause | flush-clause | read-clause | write-clause |
358 ///       update-clause | capture-clause | seq_cst-clause
359 ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)360 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
361                                      OpenMPClauseKind CKind, bool FirstClause) {
362   OMPClause *Clause = nullptr;
363   bool ErrorFound = false;
364   // Check if clause is allowed for the given directive.
365   if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
366     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
367                                                << getOpenMPDirectiveName(DKind);
368     ErrorFound = true;
369   }
370 
371   switch (CKind) {
372   case OMPC_if:
373   case OMPC_final:
374   case OMPC_num_threads:
375   case OMPC_safelen:
376   case OMPC_collapse:
377     // OpenMP [2.5, Restrictions]
378     //  At most one if clause can appear on the directive.
379     //  At most one num_threads clause can appear on the directive.
380     // OpenMP [2.8.1, simd construct, Restrictions]
381     //  Only one safelen  clause can appear on a simd directive.
382     //  Only one collapse clause can appear on a simd directive.
383     // OpenMP [2.11.1, task Construct, Restrictions]
384     //  At most one if clause can appear on the directive.
385     //  At most one final clause can appear on the directive.
386     if (!FirstClause) {
387       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
388                                                << getOpenMPClauseName(CKind);
389       ErrorFound = true;
390     }
391 
392     Clause = ParseOpenMPSingleExprClause(CKind);
393     break;
394   case OMPC_default:
395   case OMPC_proc_bind:
396     // OpenMP [2.14.3.1, Restrictions]
397     //  Only a single default clause may be specified on a parallel, task or
398     //  teams directive.
399     // OpenMP [2.5, parallel Construct, Restrictions]
400     //  At most one proc_bind clause can appear on the directive.
401     if (!FirstClause) {
402       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
403                                                << getOpenMPClauseName(CKind);
404       ErrorFound = true;
405     }
406 
407     Clause = ParseOpenMPSimpleClause(CKind);
408     break;
409   case OMPC_schedule:
410     // OpenMP [2.7.1, Restrictions, p. 3]
411     //  Only one schedule clause can appear on a loop directive.
412     if (!FirstClause) {
413       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
414                                                << getOpenMPClauseName(CKind);
415       ErrorFound = true;
416     }
417 
418     Clause = ParseOpenMPSingleExprWithArgClause(CKind);
419     break;
420   case OMPC_ordered:
421   case OMPC_nowait:
422   case OMPC_untied:
423   case OMPC_mergeable:
424   case OMPC_read:
425   case OMPC_write:
426   case OMPC_update:
427   case OMPC_capture:
428   case OMPC_seq_cst:
429     // OpenMP [2.7.1, Restrictions, p. 9]
430     //  Only one ordered clause can appear on a loop directive.
431     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
432     //  Only one nowait clause can appear on a for directive.
433     if (!FirstClause) {
434       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
435                                                << getOpenMPClauseName(CKind);
436       ErrorFound = true;
437     }
438 
439     Clause = ParseOpenMPClause(CKind);
440     break;
441   case OMPC_private:
442   case OMPC_firstprivate:
443   case OMPC_lastprivate:
444   case OMPC_shared:
445   case OMPC_reduction:
446   case OMPC_linear:
447   case OMPC_aligned:
448   case OMPC_copyin:
449   case OMPC_copyprivate:
450   case OMPC_flush:
451     Clause = ParseOpenMPVarListClause(CKind);
452     break;
453   case OMPC_unknown:
454     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
455         << getOpenMPDirectiveName(DKind);
456     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
457     break;
458   case OMPC_threadprivate:
459     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
460                                                << getOpenMPDirectiveName(DKind);
461     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
462     break;
463   }
464   return ErrorFound ? nullptr : Clause;
465 }
466 
467 /// \brief Parsing of OpenMP clauses with single expressions like 'if',
468 /// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
469 /// 'thread_limit'.
470 ///
471 ///    if-clause:
472 ///      'if' '(' expression ')'
473 ///
474 ///    final-clause:
475 ///      'final' '(' expression ')'
476 ///
477 ///    num_threads-clause:
478 ///      'num_threads' '(' expression ')'
479 ///
480 ///    safelen-clause:
481 ///      'safelen' '(' expression ')'
482 ///
483 ///    collapse-clause:
484 ///      'collapse' '(' expression ')'
485 ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind)486 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
487   SourceLocation Loc = ConsumeToken();
488 
489   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
490   if (T.expectAndConsume(diag::err_expected_lparen_after,
491                          getOpenMPClauseName(Kind)))
492     return nullptr;
493 
494   ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
495   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
496 
497   // Parse ')'.
498   T.consumeClose();
499 
500   if (Val.isInvalid())
501     return nullptr;
502 
503   return Actions.ActOnOpenMPSingleExprClause(
504       Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
505 }
506 
507 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
508 ///
509 ///    default-clause:
510 ///         'default' '(' 'none' | 'shared' ')
511 ///
512 ///    proc_bind-clause:
513 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
514 ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind)515 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
516   SourceLocation Loc = Tok.getLocation();
517   SourceLocation LOpen = ConsumeToken();
518   // Parse '('.
519   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
520   if (T.expectAndConsume(diag::err_expected_lparen_after,
521                          getOpenMPClauseName(Kind)))
522     return nullptr;
523 
524   unsigned Type = getOpenMPSimpleClauseType(
525       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
526   SourceLocation TypeLoc = Tok.getLocation();
527   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
528       Tok.isNot(tok::annot_pragma_openmp_end))
529     ConsumeAnyToken();
530 
531   // Parse ')'.
532   T.consumeClose();
533 
534   return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
535                                          Tok.getLocation());
536 }
537 
538 /// \brief Parsing of OpenMP clauses like 'ordered'.
539 ///
540 ///    ordered-clause:
541 ///         'ordered'
542 ///
543 ///    nowait-clause:
544 ///         'nowait'
545 ///
546 ///    untied-clause:
547 ///         'untied'
548 ///
549 ///    mergeable-clause:
550 ///         'mergeable'
551 ///
552 ///    read-clause:
553 ///         'read'
554 ///
ParseOpenMPClause(OpenMPClauseKind Kind)555 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
556   SourceLocation Loc = Tok.getLocation();
557   ConsumeAnyToken();
558 
559   return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
560 }
561 
562 
563 /// \brief Parsing of OpenMP clauses with single expressions and some additional
564 /// argument like 'schedule' or 'dist_schedule'.
565 ///
566 ///    schedule-clause:
567 ///      'schedule' '(' kind [',' expression ] ')'
568 ///
ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind)569 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
570   SourceLocation Loc = ConsumeToken();
571   SourceLocation CommaLoc;
572   // Parse '('.
573   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
574   if (T.expectAndConsume(diag::err_expected_lparen_after,
575                          getOpenMPClauseName(Kind)))
576     return nullptr;
577 
578   ExprResult Val;
579   unsigned Type = getOpenMPSimpleClauseType(
580       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
581   SourceLocation KLoc = Tok.getLocation();
582   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
583       Tok.isNot(tok::annot_pragma_openmp_end))
584     ConsumeAnyToken();
585 
586   if (Kind == OMPC_schedule &&
587       (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
588        Type == OMPC_SCHEDULE_guided) &&
589       Tok.is(tok::comma)) {
590     CommaLoc = ConsumeAnyToken();
591     ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
592     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
593     if (Val.isInvalid())
594       return nullptr;
595   }
596 
597   // Parse ')'.
598   T.consumeClose();
599 
600   return Actions.ActOnOpenMPSingleExprWithArgClause(
601       Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
602       T.getCloseLocation());
603 }
604 
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)605 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
606                              UnqualifiedId &ReductionId) {
607   SourceLocation TemplateKWLoc;
608   if (ReductionIdScopeSpec.isEmpty()) {
609     auto OOK = OO_None;
610     switch (P.getCurToken().getKind()) {
611     case tok::plus:
612       OOK = OO_Plus;
613       break;
614     case tok::minus:
615       OOK = OO_Minus;
616       break;
617     case tok::star:
618       OOK = OO_Star;
619       break;
620     case tok::amp:
621       OOK = OO_Amp;
622       break;
623     case tok::pipe:
624       OOK = OO_Pipe;
625       break;
626     case tok::caret:
627       OOK = OO_Caret;
628       break;
629     case tok::ampamp:
630       OOK = OO_AmpAmp;
631       break;
632     case tok::pipepipe:
633       OOK = OO_PipePipe;
634       break;
635     default:
636       break;
637     }
638     if (OOK != OO_None) {
639       SourceLocation OpLoc = P.ConsumeToken();
640       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
641       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
642       return false;
643     }
644   }
645   return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
646                               /*AllowDestructorName*/ false,
647                               /*AllowConstructorName*/ false, ParsedType(),
648                               TemplateKWLoc, ReductionId);
649 }
650 
651 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
652 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
653 ///
654 ///    private-clause:
655 ///       'private' '(' list ')'
656 ///    firstprivate-clause:
657 ///       'firstprivate' '(' list ')'
658 ///    lastprivate-clause:
659 ///       'lastprivate' '(' list ')'
660 ///    shared-clause:
661 ///       'shared' '(' list ')'
662 ///    linear-clause:
663 ///       'linear' '(' list [ ':' linear-step ] ')'
664 ///    aligned-clause:
665 ///       'aligned' '(' list [ ':' alignment ] ')'
666 ///    reduction-clause:
667 ///       'reduction' '(' reduction-identifier ':' list ')'
668 ///    copyprivate-clause:
669 ///       'copyprivate' '(' list ')'
670 ///    flush-clause:
671 ///       'flush' '(' list ')'
672 ///
ParseOpenMPVarListClause(OpenMPClauseKind Kind)673 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
674   SourceLocation Loc = Tok.getLocation();
675   SourceLocation LOpen = ConsumeToken();
676   SourceLocation ColonLoc = SourceLocation();
677   // Optional scope specifier and unqualified id for reduction identifier.
678   CXXScopeSpec ReductionIdScopeSpec;
679   UnqualifiedId ReductionId;
680   bool InvalidReductionId = false;
681   // Parse '('.
682   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
683   if (T.expectAndConsume(diag::err_expected_lparen_after,
684                          getOpenMPClauseName(Kind)))
685     return nullptr;
686 
687   // Handle reduction-identifier for reduction clause.
688   if (Kind == OMPC_reduction) {
689     ColonProtectionRAIIObject ColonRAII(*this);
690     if (getLangOpts().CPlusPlus) {
691       ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
692     }
693     InvalidReductionId =
694         ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
695     if (InvalidReductionId) {
696       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
697                 StopBeforeMatch);
698     }
699     if (Tok.is(tok::colon)) {
700       ColonLoc = ConsumeToken();
701     } else {
702       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
703     }
704   }
705 
706   SmallVector<Expr *, 5> Vars;
707   bool IsComma = !InvalidReductionId;
708   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
709   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
710                      Tok.isNot(tok::annot_pragma_openmp_end))) {
711     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
712     // Parse variable
713     ExprResult VarExpr =
714         Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
715     if (VarExpr.isUsable()) {
716       Vars.push_back(VarExpr.get());
717     } else {
718       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
719                 StopBeforeMatch);
720     }
721     // Skip ',' if any
722     IsComma = Tok.is(tok::comma);
723     if (IsComma)
724       ConsumeToken();
725     else if (Tok.isNot(tok::r_paren) &&
726              Tok.isNot(tok::annot_pragma_openmp_end) &&
727              (!MayHaveTail || Tok.isNot(tok::colon)))
728       Diag(Tok, diag::err_omp_expected_punc)
729           << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
730                                    : getOpenMPClauseName(Kind))
731           << (Kind == OMPC_flush);
732   }
733 
734   // Parse ':' linear-step (or ':' alignment).
735   Expr *TailExpr = nullptr;
736   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
737   if (MustHaveTail) {
738     ColonLoc = Tok.getLocation();
739     ConsumeToken();
740     ExprResult Tail =
741         Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
742     if (Tail.isUsable())
743       TailExpr = Tail.get();
744     else
745       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
746                 StopBeforeMatch);
747   }
748 
749   // Parse ')'.
750   T.consumeClose();
751   if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
752     return nullptr;
753 
754   return Actions.ActOnOpenMPVarListClause(
755       Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
756       ReductionIdScopeSpec,
757       ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
758                             : DeclarationNameInfo());
759 }
760 
761