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