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
ParseOpenMPDirectiveKind(Parser & P)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 ///
ParseOpenMPDeclarativeDirective()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
ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed)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 ///
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,SmallVectorImpl<Expr * > & VarList,bool AllowScopeSpecifier)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 ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)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 ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind)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 ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind)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 ///
ParseOpenMPClause(OpenMPClauseKind Kind)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 ///
ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind)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
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)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 ///
ParseOpenMPVarListClause(OpenMPClauseKind Kind)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
820