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