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