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