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