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