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