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 
23 using namespace clang;
24 
25 //===----------------------------------------------------------------------===//
26 // OpenMP declarative directives.
27 //===----------------------------------------------------------------------===//
28 
ParseOpenMPDirectiveKind(Parser & P)29 static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
30   // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
31   // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
32   // TODO: add other combined directives in topological order.
33   const OpenMPDirectiveKind F[][3] = {
34       {OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/,
35        OMPD_cancellation_point},
36       {OMPD_target, OMPD_unknown /*data*/, OMPD_target_data},
37       {OMPD_for, OMPD_simd, OMPD_for_simd},
38       {OMPD_parallel, OMPD_for, OMPD_parallel_for},
39       {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
40       {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
41       {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}};
42   auto Tok = P.getCurToken();
43   auto DKind =
44       Tok.isAnnotation()
45           ? OMPD_unknown
46           : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
47 
48   bool TokenMatched = false;
49   for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
50     if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
51       TokenMatched =
52           (i == 0) &&
53           !P.getPreprocessor().getSpelling(Tok).compare("cancellation");
54     } else {
55       TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown;
56     }
57 
58     if (TokenMatched) {
59       Tok = P.getPreprocessor().LookAhead(0);
60       auto TokenIsAnnotation = Tok.isAnnotation();
61       auto SDKind =
62           TokenIsAnnotation
63               ? OMPD_unknown
64               : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
65 
66       if (!TokenIsAnnotation && SDKind == OMPD_unknown) {
67         TokenMatched =
68             ((i == 0) &&
69              !P.getPreprocessor().getSpelling(Tok).compare("point")) ||
70             ((i == 1) && !P.getPreprocessor().getSpelling(Tok).compare("data"));
71       } else {
72         TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown;
73       }
74 
75       if (TokenMatched) {
76         P.ConsumeToken();
77         DKind = F[i][2];
78       }
79     }
80   }
81   return DKind;
82 }
83 
84 /// \brief Parsing of declarative OpenMP directives.
85 ///
86 ///       threadprivate-directive:
87 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
88 ///
ParseOpenMPDeclarativeDirective()89 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
90   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
91   ParenBraceBracketBalancer BalancerRAIIObj(*this);
92 
93   SourceLocation Loc = ConsumeToken();
94   SmallVector<Expr *, 5> Identifiers;
95   auto DKind = ParseOpenMPDirectiveKind(*this);
96 
97   switch (DKind) {
98   case OMPD_threadprivate:
99     ConsumeToken();
100     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
101       // The last seen token is annot_pragma_openmp_end - need to check for
102       // extra tokens.
103       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
104         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
105             << getOpenMPDirectiveName(OMPD_threadprivate);
106         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
107       }
108       // Skip the last annot_pragma_openmp_end.
109       ConsumeToken();
110       return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
111     }
112     break;
113   case OMPD_unknown:
114     Diag(Tok, diag::err_omp_unknown_directive);
115     break;
116   case OMPD_parallel:
117   case OMPD_simd:
118   case OMPD_task:
119   case OMPD_taskyield:
120   case OMPD_barrier:
121   case OMPD_taskwait:
122   case OMPD_taskgroup:
123   case OMPD_flush:
124   case OMPD_for:
125   case OMPD_for_simd:
126   case OMPD_sections:
127   case OMPD_section:
128   case OMPD_single:
129   case OMPD_master:
130   case OMPD_ordered:
131   case OMPD_critical:
132   case OMPD_parallel_for:
133   case OMPD_parallel_for_simd:
134   case OMPD_parallel_sections:
135   case OMPD_atomic:
136   case OMPD_target:
137   case OMPD_teams:
138   case OMPD_cancellation_point:
139   case OMPD_cancel:
140   case OMPD_target_data:
141   case OMPD_taskloop:
142   case OMPD_taskloop_simd:
143   case OMPD_distribute:
144     Diag(Tok, diag::err_omp_unexpected_directive)
145         << getOpenMPDirectiveName(DKind);
146     break;
147   }
148   SkipUntil(tok::annot_pragma_openmp_end);
149   return DeclGroupPtrTy();
150 }
151 
152 /// \brief Parsing of declarative or executable OpenMP directives.
153 ///
154 ///       threadprivate-directive:
155 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
156 ///         annot_pragma_openmp_end
157 ///
158 ///       executable-directive:
159 ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
160 ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
161 ///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
162 ///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
163 ///         'for simd' | 'parallel for simd' | 'target' | 'target data' |
164 ///         'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' {clause} |
165 ///         'distribute'
166 ///         annot_pragma_openmp_end
167 ///
168 StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed)169 Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
170   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
171   ParenBraceBracketBalancer BalancerRAIIObj(*this);
172   SmallVector<Expr *, 5> Identifiers;
173   SmallVector<OMPClause *, 5> Clauses;
174   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
175   FirstClauses(OMPC_unknown + 1);
176   unsigned ScopeFlags =
177       Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
178   SourceLocation Loc = ConsumeToken(), EndLoc;
179   auto DKind = ParseOpenMPDirectiveKind(*this);
180   OpenMPDirectiveKind CancelRegion = OMPD_unknown;
181   // Name of critical directive.
182   DeclarationNameInfo DirName;
183   StmtResult Directive = StmtError();
184   bool HasAssociatedStatement = true;
185   bool FlushHasClause = false;
186 
187   switch (DKind) {
188   case OMPD_threadprivate:
189     ConsumeToken();
190     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
191       // The last seen token is annot_pragma_openmp_end - need to check for
192       // extra tokens.
193       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
194         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
195             << getOpenMPDirectiveName(OMPD_threadprivate);
196         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
197       }
198       DeclGroupPtrTy Res =
199           Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
200       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
201     }
202     SkipUntil(tok::annot_pragma_openmp_end);
203     break;
204   case OMPD_flush:
205     if (PP.LookAhead(0).is(tok::l_paren)) {
206       FlushHasClause = true;
207       // Push copy of the current token back to stream to properly parse
208       // pseudo-clause OMPFlushClause.
209       PP.EnterToken(Tok);
210     }
211   case OMPD_taskyield:
212   case OMPD_barrier:
213   case OMPD_taskwait:
214   case OMPD_cancellation_point:
215   case OMPD_cancel:
216     if (!StandAloneAllowed) {
217       Diag(Tok, diag::err_omp_immediate_directive)
218           << getOpenMPDirectiveName(DKind) << 0;
219     }
220     HasAssociatedStatement = false;
221     // Fall through for further analysis.
222   case OMPD_parallel:
223   case OMPD_simd:
224   case OMPD_for:
225   case OMPD_for_simd:
226   case OMPD_sections:
227   case OMPD_single:
228   case OMPD_section:
229   case OMPD_master:
230   case OMPD_critical:
231   case OMPD_parallel_for:
232   case OMPD_parallel_for_simd:
233   case OMPD_parallel_sections:
234   case OMPD_task:
235   case OMPD_ordered:
236   case OMPD_atomic:
237   case OMPD_target:
238   case OMPD_teams:
239   case OMPD_taskgroup:
240   case OMPD_target_data:
241   case OMPD_taskloop:
242   case OMPD_taskloop_simd:
243   case OMPD_distribute: {
244     ConsumeToken();
245     // Parse directive name of the 'critical' directive if any.
246     if (DKind == OMPD_critical) {
247       BalancedDelimiterTracker T(*this, tok::l_paren,
248                                  tok::annot_pragma_openmp_end);
249       if (!T.consumeOpen()) {
250         if (Tok.isAnyIdentifier()) {
251           DirName =
252               DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
253           ConsumeAnyToken();
254         } else {
255           Diag(Tok, diag::err_omp_expected_identifier_for_critical);
256         }
257         T.consumeClose();
258       }
259     } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
260       CancelRegion = ParseOpenMPDirectiveKind(*this);
261       if (Tok.isNot(tok::annot_pragma_openmp_end))
262         ConsumeToken();
263     }
264 
265     if (isOpenMPLoopDirective(DKind))
266       ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
267     if (isOpenMPSimdDirective(DKind))
268       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
269     ParseScope OMPDirectiveScope(this, ScopeFlags);
270     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
271 
272     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
273       OpenMPClauseKind CKind =
274           Tok.isAnnotation()
275               ? OMPC_unknown
276               : FlushHasClause ? OMPC_flush
277                                : getOpenMPClauseKind(PP.getSpelling(Tok));
278       Actions.StartOpenMPClause(CKind);
279       FlushHasClause = false;
280       OMPClause *Clause =
281           ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
282       FirstClauses[CKind].setInt(true);
283       if (Clause) {
284         FirstClauses[CKind].setPointer(Clause);
285         Clauses.push_back(Clause);
286       }
287 
288       // Skip ',' if any.
289       if (Tok.is(tok::comma))
290         ConsumeToken();
291       Actions.EndOpenMPClause();
292     }
293     // End location of the directive.
294     EndLoc = Tok.getLocation();
295     // Consume final annot_pragma_openmp_end.
296     ConsumeToken();
297 
298     // OpenMP [2.13.8, ordered Construct, Syntax]
299     // If the depend clause is specified, the ordered construct is a stand-alone
300     // directive.
301     if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
302       if (!StandAloneAllowed) {
303         Diag(Loc, diag::err_omp_immediate_directive)
304             << getOpenMPDirectiveName(DKind) << 1
305             << getOpenMPClauseName(OMPC_depend);
306       }
307       HasAssociatedStatement = false;
308     }
309 
310     StmtResult AssociatedStmt;
311     if (HasAssociatedStatement) {
312       // The body is a block scope like in Lambdas and Blocks.
313       Sema::CompoundScopeRAII CompoundScope(Actions);
314       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
315       Actions.ActOnStartOfCompoundStmt();
316       // Parse statement
317       AssociatedStmt = ParseStatement();
318       Actions.ActOnFinishOfCompoundStmt();
319       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
320     }
321     Directive = Actions.ActOnOpenMPExecutableDirective(
322         DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
323         EndLoc);
324 
325     // Exit scope.
326     Actions.EndOpenMPDSABlock(Directive.get());
327     OMPDirectiveScope.Exit();
328     break;
329   }
330   case OMPD_unknown:
331     Diag(Tok, diag::err_omp_unknown_directive);
332     SkipUntil(tok::annot_pragma_openmp_end);
333     break;
334   }
335   return Directive;
336 }
337 
338 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
339 /// directive.
340 ///
341 ///   simple-variable-list:
342 ///         '(' id-expression {, id-expression} ')'
343 ///
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,SmallVectorImpl<Expr * > & VarList,bool AllowScopeSpecifier)344 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
345                                       SmallVectorImpl<Expr *> &VarList,
346                                       bool AllowScopeSpecifier) {
347   VarList.clear();
348   // Parse '('.
349   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
350   if (T.expectAndConsume(diag::err_expected_lparen_after,
351                          getOpenMPDirectiveName(Kind)))
352     return true;
353   bool IsCorrect = true;
354   bool NoIdentIsFound = true;
355 
356   // Read tokens while ')' or annot_pragma_openmp_end is not found.
357   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
358     CXXScopeSpec SS;
359     SourceLocation TemplateKWLoc;
360     UnqualifiedId Name;
361     // Read var name.
362     Token PrevTok = Tok;
363     NoIdentIsFound = false;
364 
365     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
366         ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
367       IsCorrect = false;
368       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
369                 StopBeforeMatch);
370     } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
371                                   TemplateKWLoc, Name)) {
372       IsCorrect = false;
373       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
374                 StopBeforeMatch);
375     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
376                Tok.isNot(tok::annot_pragma_openmp_end)) {
377       IsCorrect = false;
378       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
379                 StopBeforeMatch);
380       Diag(PrevTok.getLocation(), diag::err_expected)
381           << tok::identifier
382           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
383     } else {
384       DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
385       ExprResult Res =
386           Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
387       if (Res.isUsable())
388         VarList.push_back(Res.get());
389     }
390     // Consume ','.
391     if (Tok.is(tok::comma)) {
392       ConsumeToken();
393     }
394   }
395 
396   if (NoIdentIsFound) {
397     Diag(Tok, diag::err_expected) << tok::identifier;
398     IsCorrect = false;
399   }
400 
401   // Parse ')'.
402   IsCorrect = !T.consumeClose() && IsCorrect;
403 
404   return !IsCorrect && VarList.empty();
405 }
406 
407 /// \brief Parsing of OpenMP clauses.
408 ///
409 ///    clause:
410 ///       if-clause | final-clause | num_threads-clause | safelen-clause |
411 ///       default-clause | private-clause | firstprivate-clause | shared-clause
412 ///       | linear-clause | aligned-clause | collapse-clause |
413 ///       lastprivate-clause | reduction-clause | proc_bind-clause |
414 ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
415 ///       mergeable-clause | flush-clause | read-clause | write-clause |
416 ///       update-clause | capture-clause | seq_cst-clause | device-clause |
417 ///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
418 ///       thread_limit-clause | priority-clause | grainsize-clause |
419 ///       nogroup-clause | num_tasks-clause | hint-clause
420 ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)421 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
422                                      OpenMPClauseKind CKind, bool FirstClause) {
423   OMPClause *Clause = nullptr;
424   bool ErrorFound = false;
425   // Check if clause is allowed for the given directive.
426   if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
427     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
428                                                << getOpenMPDirectiveName(DKind);
429     ErrorFound = true;
430   }
431 
432   switch (CKind) {
433   case OMPC_final:
434   case OMPC_num_threads:
435   case OMPC_safelen:
436   case OMPC_simdlen:
437   case OMPC_collapse:
438   case OMPC_ordered:
439   case OMPC_device:
440   case OMPC_num_teams:
441   case OMPC_thread_limit:
442   case OMPC_priority:
443   case OMPC_grainsize:
444   case OMPC_num_tasks:
445   case OMPC_hint:
446     // OpenMP [2.5, Restrictions]
447     //  At most one num_threads clause can appear on the directive.
448     // OpenMP [2.8.1, simd construct, Restrictions]
449     //  Only one safelen  clause can appear on a simd directive.
450     //  Only one simdlen  clause can appear on a simd directive.
451     //  Only one collapse clause can appear on a simd directive.
452     // OpenMP [2.9.1, target data construct, Restrictions]
453     //  At most one device clause can appear on the directive.
454     // OpenMP [2.11.1, task Construct, Restrictions]
455     //  At most one if clause can appear on the directive.
456     //  At most one final clause can appear on the directive.
457     // OpenMP [teams Construct, Restrictions]
458     //  At most one num_teams clause can appear on the directive.
459     //  At most one thread_limit clause can appear on the directive.
460     // OpenMP [2.9.1, task Construct, Restrictions]
461     // At most one priority clause can appear on the directive.
462     // OpenMP [2.9.2, taskloop Construct, Restrictions]
463     // At most one grainsize clause can appear on the directive.
464     // OpenMP [2.9.2, taskloop Construct, Restrictions]
465     // At most one num_tasks clause can appear on the directive.
466     if (!FirstClause) {
467       Diag(Tok, diag::err_omp_more_one_clause)
468           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
469       ErrorFound = true;
470     }
471 
472     if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
473       Clause = ParseOpenMPClause(CKind);
474     else
475       Clause = ParseOpenMPSingleExprClause(CKind);
476     break;
477   case OMPC_default:
478   case OMPC_proc_bind:
479     // OpenMP [2.14.3.1, Restrictions]
480     //  Only a single default clause may be specified on a parallel, task or
481     //  teams directive.
482     // OpenMP [2.5, parallel Construct, Restrictions]
483     //  At most one proc_bind clause can appear on the directive.
484     if (!FirstClause) {
485       Diag(Tok, diag::err_omp_more_one_clause)
486           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
487       ErrorFound = true;
488     }
489 
490     Clause = ParseOpenMPSimpleClause(CKind);
491     break;
492   case OMPC_schedule:
493     // OpenMP [2.7.1, Restrictions, p. 3]
494     //  Only one schedule clause can appear on a loop directive.
495     if (!FirstClause) {
496       Diag(Tok, diag::err_omp_more_one_clause)
497           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
498       ErrorFound = true;
499     }
500 
501   case OMPC_if:
502     Clause = ParseOpenMPSingleExprWithArgClause(CKind);
503     break;
504   case OMPC_nowait:
505   case OMPC_untied:
506   case OMPC_mergeable:
507   case OMPC_read:
508   case OMPC_write:
509   case OMPC_update:
510   case OMPC_capture:
511   case OMPC_seq_cst:
512   case OMPC_threads:
513   case OMPC_simd:
514   case OMPC_nogroup:
515     // OpenMP [2.7.1, Restrictions, p. 9]
516     //  Only one ordered clause can appear on a loop directive.
517     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
518     //  Only one nowait clause can appear on a for directive.
519     if (!FirstClause) {
520       Diag(Tok, diag::err_omp_more_one_clause)
521           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
522       ErrorFound = true;
523     }
524 
525     Clause = ParseOpenMPClause(CKind);
526     break;
527   case OMPC_private:
528   case OMPC_firstprivate:
529   case OMPC_lastprivate:
530   case OMPC_shared:
531   case OMPC_reduction:
532   case OMPC_linear:
533   case OMPC_aligned:
534   case OMPC_copyin:
535   case OMPC_copyprivate:
536   case OMPC_flush:
537   case OMPC_depend:
538   case OMPC_map:
539     Clause = ParseOpenMPVarListClause(DKind, CKind);
540     break;
541   case OMPC_unknown:
542     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
543         << getOpenMPDirectiveName(DKind);
544     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
545     break;
546   case OMPC_threadprivate:
547     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
548                                                << getOpenMPDirectiveName(DKind);
549     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
550     break;
551   }
552   return ErrorFound ? nullptr : Clause;
553 }
554 
555 /// \brief Parsing of OpenMP clauses with single expressions like 'final',
556 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
557 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
558 ///
559 ///    final-clause:
560 ///      'final' '(' expression ')'
561 ///
562 ///    num_threads-clause:
563 ///      'num_threads' '(' expression ')'
564 ///
565 ///    safelen-clause:
566 ///      'safelen' '(' expression ')'
567 ///
568 ///    simdlen-clause:
569 ///      'simdlen' '(' expression ')'
570 ///
571 ///    collapse-clause:
572 ///      'collapse' '(' expression ')'
573 ///
574 ///    priority-clause:
575 ///      'priority' '(' expression ')'
576 ///
577 ///    grainsize-clause:
578 ///      'grainsize' '(' expression ')'
579 ///
580 ///    num_tasks-clause:
581 ///      'num_tasks' '(' expression ')'
582 ///
583 ///    hint-clause:
584 ///      'hint' '(' expression ')'
585 ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind)586 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
587   SourceLocation Loc = ConsumeToken();
588 
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   SourceLocation ELoc = Tok.getLocation();
595   ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
596   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
597   Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
598 
599   // Parse ')'.
600   T.consumeClose();
601 
602   if (Val.isInvalid())
603     return nullptr;
604 
605   return Actions.ActOnOpenMPSingleExprClause(
606       Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
607 }
608 
609 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
610 ///
611 ///    default-clause:
612 ///         'default' '(' 'none' | 'shared' ')
613 ///
614 ///    proc_bind-clause:
615 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
616 ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind)617 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
618   SourceLocation Loc = Tok.getLocation();
619   SourceLocation LOpen = ConsumeToken();
620   // Parse '('.
621   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
622   if (T.expectAndConsume(diag::err_expected_lparen_after,
623                          getOpenMPClauseName(Kind)))
624     return nullptr;
625 
626   unsigned Type = getOpenMPSimpleClauseType(
627       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
628   SourceLocation TypeLoc = Tok.getLocation();
629   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
630       Tok.isNot(tok::annot_pragma_openmp_end))
631     ConsumeAnyToken();
632 
633   // Parse ')'.
634   T.consumeClose();
635 
636   return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
637                                          Tok.getLocation());
638 }
639 
640 /// \brief Parsing of OpenMP clauses like 'ordered'.
641 ///
642 ///    ordered-clause:
643 ///         'ordered'
644 ///
645 ///    nowait-clause:
646 ///         'nowait'
647 ///
648 ///    untied-clause:
649 ///         'untied'
650 ///
651 ///    mergeable-clause:
652 ///         'mergeable'
653 ///
654 ///    read-clause:
655 ///         'read'
656 ///
657 ///    threads-clause:
658 ///         'threads'
659 ///
660 ///    simd-clause:
661 ///         'simd'
662 ///
663 ///    nogroup-clause:
664 ///         'nogroup'
665 ///
ParseOpenMPClause(OpenMPClauseKind Kind)666 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
667   SourceLocation Loc = Tok.getLocation();
668   ConsumeAnyToken();
669 
670   return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
671 }
672 
673 
674 /// \brief Parsing of OpenMP clauses with single expressions and some additional
675 /// argument like 'schedule' or 'dist_schedule'.
676 ///
677 ///    schedule-clause:
678 ///      'schedule' '(' kind [',' expression ] ')'
679 ///
680 ///    if-clause:
681 ///      'if' '(' [ directive-name-modifier ':' ] expression ')'
682 ///
ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind)683 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
684   SourceLocation Loc = ConsumeToken();
685   SourceLocation DelimLoc;
686   // Parse '('.
687   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
688   if (T.expectAndConsume(diag::err_expected_lparen_after,
689                          getOpenMPClauseName(Kind)))
690     return nullptr;
691 
692   ExprResult Val;
693   unsigned Arg;
694   SourceLocation KLoc;
695   if (Kind == OMPC_schedule) {
696     Arg = getOpenMPSimpleClauseType(
697         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
698     KLoc = Tok.getLocation();
699     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
700         Tok.isNot(tok::annot_pragma_openmp_end))
701       ConsumeAnyToken();
702     if ((Arg == OMPC_SCHEDULE_static || Arg == OMPC_SCHEDULE_dynamic ||
703          Arg == OMPC_SCHEDULE_guided) &&
704         Tok.is(tok::comma))
705       DelimLoc = ConsumeAnyToken();
706   } else {
707     assert(Kind == OMPC_if);
708     KLoc = Tok.getLocation();
709     Arg = ParseOpenMPDirectiveKind(*this);
710     if (Arg != OMPD_unknown) {
711       ConsumeToken();
712       if (Tok.is(tok::colon))
713         DelimLoc = ConsumeToken();
714       else
715         Diag(Tok, diag::warn_pragma_expected_colon)
716             << "directive name modifier";
717     }
718   }
719 
720   bool NeedAnExpression =
721       (Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if;
722   if (NeedAnExpression) {
723     SourceLocation ELoc = Tok.getLocation();
724     ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
725     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
726     Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
727   }
728 
729   // Parse ')'.
730   T.consumeClose();
731 
732   if (NeedAnExpression && Val.isInvalid())
733     return nullptr;
734 
735   return Actions.ActOnOpenMPSingleExprWithArgClause(
736       Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
737       T.getCloseLocation());
738 }
739 
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)740 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
741                              UnqualifiedId &ReductionId) {
742   SourceLocation TemplateKWLoc;
743   if (ReductionIdScopeSpec.isEmpty()) {
744     auto OOK = OO_None;
745     switch (P.getCurToken().getKind()) {
746     case tok::plus:
747       OOK = OO_Plus;
748       break;
749     case tok::minus:
750       OOK = OO_Minus;
751       break;
752     case tok::star:
753       OOK = OO_Star;
754       break;
755     case tok::amp:
756       OOK = OO_Amp;
757       break;
758     case tok::pipe:
759       OOK = OO_Pipe;
760       break;
761     case tok::caret:
762       OOK = OO_Caret;
763       break;
764     case tok::ampamp:
765       OOK = OO_AmpAmp;
766       break;
767     case tok::pipepipe:
768       OOK = OO_PipePipe;
769       break;
770     default:
771       break;
772     }
773     if (OOK != OO_None) {
774       SourceLocation OpLoc = P.ConsumeToken();
775       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
776       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
777       return false;
778     }
779   }
780   return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
781                               /*AllowDestructorName*/ false,
782                               /*AllowConstructorName*/ false, ParsedType(),
783                               TemplateKWLoc, ReductionId);
784 }
785 
786 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
787 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
788 ///
789 ///    private-clause:
790 ///       'private' '(' list ')'
791 ///    firstprivate-clause:
792 ///       'firstprivate' '(' list ')'
793 ///    lastprivate-clause:
794 ///       'lastprivate' '(' list ')'
795 ///    shared-clause:
796 ///       'shared' '(' list ')'
797 ///    linear-clause:
798 ///       'linear' '(' linear-list [ ':' linear-step ] ')'
799 ///    aligned-clause:
800 ///       'aligned' '(' list [ ':' alignment ] ')'
801 ///    reduction-clause:
802 ///       'reduction' '(' reduction-identifier ':' list ')'
803 ///    copyprivate-clause:
804 ///       'copyprivate' '(' list ')'
805 ///    flush-clause:
806 ///       'flush' '(' list ')'
807 ///    depend-clause:
808 ///       'depend' '(' in | out | inout : list | source ')'
809 ///    map-clause:
810 ///       'map' '(' [ [ always , ]
811 ///          to | from | tofrom | alloc | release | delete ':' ] list ')';
812 ///
813 /// For 'linear' clause linear-list may have the following forms:
814 ///  list
815 ///  modifier(list)
816 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind)817 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
818                                             OpenMPClauseKind Kind) {
819   SourceLocation Loc = Tok.getLocation();
820   SourceLocation LOpen = ConsumeToken();
821   SourceLocation ColonLoc = SourceLocation();
822   // Optional scope specifier and unqualified id for reduction identifier.
823   CXXScopeSpec ReductionIdScopeSpec;
824   UnqualifiedId ReductionId;
825   bool InvalidReductionId = false;
826   OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
827   // OpenMP 4.1 [2.15.3.7, linear Clause]
828   //  If no modifier is specified it is assumed to be val.
829   OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val;
830   OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
831   OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
832   bool MapTypeModifierSpecified = false;
833   bool UnexpectedId = false;
834   SourceLocation DepLinMapLoc;
835 
836   // Parse '('.
837   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
838   if (T.expectAndConsume(diag::err_expected_lparen_after,
839                          getOpenMPClauseName(Kind)))
840     return nullptr;
841 
842   bool NeedRParenForLinear = false;
843   BalancedDelimiterTracker LinearT(*this, tok::l_paren,
844                                   tok::annot_pragma_openmp_end);
845   // Handle reduction-identifier for reduction clause.
846   if (Kind == OMPC_reduction) {
847     ColonProtectionRAIIObject ColonRAII(*this);
848     if (getLangOpts().CPlusPlus) {
849       ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
850     }
851     InvalidReductionId =
852         ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
853     if (InvalidReductionId) {
854       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
855                 StopBeforeMatch);
856     }
857     if (Tok.is(tok::colon)) {
858       ColonLoc = ConsumeToken();
859     } else {
860       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
861     }
862   } else if (Kind == OMPC_depend) {
863   // Handle dependency type for depend clause.
864     ColonProtectionRAIIObject ColonRAII(*this);
865     DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
866         Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
867     DepLinMapLoc = Tok.getLocation();
868 
869     if (DepKind == OMPC_DEPEND_unknown) {
870       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
871                 StopBeforeMatch);
872     } else {
873       ConsumeToken();
874       // Special processing for depend(source) clause.
875       if (DKind == OMPD_ordered && DepKind == OMPC_DEPEND_source) {
876         // Parse ')'.
877         T.consumeClose();
878         return Actions.ActOnOpenMPVarListClause(
879             Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen,
880             /*ColonLoc=*/SourceLocation(), Tok.getLocation(),
881             ReductionIdScopeSpec, DeclarationNameInfo(), DepKind,
882             LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
883       }
884     }
885     if (Tok.is(tok::colon)) {
886       ColonLoc = ConsumeToken();
887     } else {
888       Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
889                                       : diag::warn_pragma_expected_colon)
890           << "dependency type";
891     }
892   } else if (Kind == OMPC_linear) {
893     // Try to parse modifier if any.
894     if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
895       LinearModifier = static_cast<OpenMPLinearClauseKind>(
896           getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
897       DepLinMapLoc = ConsumeToken();
898       LinearT.consumeOpen();
899       NeedRParenForLinear = true;
900     }
901   } else if (Kind == OMPC_map) {
902     // Handle map type for map clause.
903     ColonProtectionRAIIObject ColonRAII(*this);
904 
905     // the first identifier may be a list item, a map-type or
906     //   a map-type-modifier
907     MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
908         Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
909     DepLinMapLoc = Tok.getLocation();
910     bool ColonExpected = false;
911 
912     if (Tok.is(tok::identifier)) {
913       if (PP.LookAhead(0).is(tok::colon)) {
914         MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
915             Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
916         if (MapType == OMPC_MAP_unknown) {
917           Diag(Tok, diag::err_omp_unknown_map_type);
918         } else if (MapType == OMPC_MAP_always) {
919           Diag(Tok, diag::err_omp_map_type_missing);
920         }
921         ConsumeToken();
922       } else if (PP.LookAhead(0).is(tok::comma)) {
923         if (PP.LookAhead(1).is(tok::identifier) &&
924             PP.LookAhead(2).is(tok::colon)) {
925           MapTypeModifier =
926               static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
927                    Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
928           if (MapTypeModifier != OMPC_MAP_always) {
929             Diag(Tok, diag::err_omp_unknown_map_type_modifier);
930             MapTypeModifier = OMPC_MAP_unknown;
931           } else {
932             MapTypeModifierSpecified = true;
933           }
934 
935           ConsumeToken();
936           ConsumeToken();
937 
938           MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
939               Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
940           if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) {
941             Diag(Tok, diag::err_omp_unknown_map_type);
942           }
943           ConsumeToken();
944         } else {
945           MapType = OMPC_MAP_tofrom;
946         }
947       } else {
948         MapType = OMPC_MAP_tofrom;
949       }
950     } else {
951       UnexpectedId = true;
952     }
953 
954     if (Tok.is(tok::colon)) {
955       ColonLoc = ConsumeToken();
956     } else if (ColonExpected) {
957       Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
958     }
959   }
960 
961   SmallVector<Expr *, 5> Vars;
962   bool IsComma =
963       ((Kind != OMPC_reduction) && (Kind != OMPC_depend) &&
964        (Kind != OMPC_map)) ||
965       ((Kind == OMPC_reduction) && !InvalidReductionId) ||
966       ((Kind == OMPC_map) && (UnexpectedId || MapType != OMPC_MAP_unknown) &&
967        (!MapTypeModifierSpecified ||
968         (MapTypeModifierSpecified && MapTypeModifier == OMPC_MAP_always))) ||
969       ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
970   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
971   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
972                      Tok.isNot(tok::annot_pragma_openmp_end))) {
973     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
974     // Parse variable
975     ExprResult VarExpr =
976         Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
977     if (VarExpr.isUsable()) {
978       Vars.push_back(VarExpr.get());
979     } else {
980       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
981                 StopBeforeMatch);
982     }
983     // Skip ',' if any
984     IsComma = Tok.is(tok::comma);
985     if (IsComma)
986       ConsumeToken();
987     else if (Tok.isNot(tok::r_paren) &&
988              Tok.isNot(tok::annot_pragma_openmp_end) &&
989              (!MayHaveTail || Tok.isNot(tok::colon)))
990       Diag(Tok, diag::err_omp_expected_punc)
991           << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
992                                    : getOpenMPClauseName(Kind))
993           << (Kind == OMPC_flush);
994   }
995 
996   // Parse ')' for linear clause with modifier.
997   if (NeedRParenForLinear)
998     LinearT.consumeClose();
999 
1000   // Parse ':' linear-step (or ':' alignment).
1001   Expr *TailExpr = nullptr;
1002   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
1003   if (MustHaveTail) {
1004     ColonLoc = Tok.getLocation();
1005     SourceLocation ELoc = ConsumeToken();
1006     ExprResult Tail = ParseAssignmentExpression();
1007     Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
1008     if (Tail.isUsable())
1009       TailExpr = Tail.get();
1010     else
1011       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1012                 StopBeforeMatch);
1013   }
1014 
1015   // Parse ')'.
1016   T.consumeClose();
1017   if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
1018       (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
1019       (Kind == OMPC_map && MapType == OMPC_MAP_unknown) ||
1020       InvalidReductionId) {
1021     return nullptr;
1022   }
1023 
1024   return Actions.ActOnOpenMPVarListClause(
1025       Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
1026       ReductionIdScopeSpec,
1027       ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
1028                             : DeclarationNameInfo(),
1029       DepKind, LinearModifier, MapTypeModifier, MapType, DepLinMapLoc);
1030 }
1031 
1032