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