1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
12 //===----------------------------------------------------------------------===//
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"
23 using namespace clang;
25 //===----------------------------------------------------------------------===//
26 // OpenMP declarative directives.
27 //===----------------------------------------------------------------------===//
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 auto Tok = P.getCurToken();
45 : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
47 bool TokenMatched = false;
48 for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
49 if (!Tok.isAnnotation() && DKind == OMPD_unknown) {
52 !P.getPreprocessor().getSpelling(Tok).compare("cancellation");
54 TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown;
58 Tok = P.getPreprocessor().LookAhead(0);
59 auto TokenIsAnnotation = Tok.isAnnotation();
63 : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
65 if (!TokenIsAnnotation && SDKind == OMPD_unknown) {
68 !P.getPreprocessor().getSpelling(Tok).compare("point")) ||
69 ((i == 1) && !P.getPreprocessor().getSpelling(Tok).compare("data"));
71 TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown;
83 /// \brief Parsing of declarative OpenMP directives.
85 /// threadprivate-directive:
86 /// annot_pragma_openmp 'threadprivate' simple-variable-list
88 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
89 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
90 ParenBraceBracketBalancer BalancerRAIIObj(*this);
92 SourceLocation Loc = ConsumeToken();
93 SmallVector<Expr *, 5> Identifiers;
94 auto DKind = ParseOpenMPDirectiveKind(*this);
97 case OMPD_threadprivate:
99 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
100 // The last seen token is annot_pragma_openmp_end - need to check for
102 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
103 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
104 << getOpenMPDirectiveName(OMPD_threadprivate);
105 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
107 // Skip the last annot_pragma_openmp_end.
109 return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
113 Diag(Tok, diag::err_omp_unknown_directive);
131 case OMPD_parallel_for:
132 case OMPD_parallel_for_simd:
133 case OMPD_parallel_sections:
137 case OMPD_cancellation_point:
139 case OMPD_target_data:
140 Diag(Tok, diag::err_omp_unexpected_directive)
141 << getOpenMPDirectiveName(DKind);
144 SkipUntil(tok::annot_pragma_openmp_end);
145 return DeclGroupPtrTy();
148 /// \brief Parsing of declarative or executable OpenMP directives.
150 /// threadprivate-directive:
151 /// annot_pragma_openmp 'threadprivate' simple-variable-list
152 /// annot_pragma_openmp_end
154 /// executable-directive:
155 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
156 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
157 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
158 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
159 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
160 /// 'taskgroup' | 'teams' {clause}
161 /// annot_pragma_openmp_end
164 Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
165 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
166 ParenBraceBracketBalancer BalancerRAIIObj(*this);
167 SmallVector<Expr *, 5> Identifiers;
168 SmallVector<OMPClause *, 5> Clauses;
169 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
170 FirstClauses(OMPC_unknown + 1);
171 unsigned ScopeFlags =
172 Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
173 SourceLocation Loc = ConsumeToken(), EndLoc;
174 auto DKind = ParseOpenMPDirectiveKind(*this);
175 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
176 // Name of critical directive.
177 DeclarationNameInfo DirName;
178 StmtResult Directive = StmtError();
179 bool HasAssociatedStatement = true;
180 bool FlushHasClause = false;
183 case OMPD_threadprivate:
185 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
186 // The last seen token is annot_pragma_openmp_end - need to check for
188 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
189 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
190 << getOpenMPDirectiveName(OMPD_threadprivate);
191 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
194 Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
195 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
197 SkipUntil(tok::annot_pragma_openmp_end);
200 if (PP.LookAhead(0).is(tok::l_paren)) {
201 FlushHasClause = true;
202 // Push copy of the current token back to stream to properly parse
203 // pseudo-clause OMPFlushClause.
209 case OMPD_cancellation_point:
211 if (!StandAloneAllowed) {
212 Diag(Tok, diag::err_omp_immediate_directive)
213 << getOpenMPDirectiveName(DKind);
215 HasAssociatedStatement = false;
216 // Fall through for further analysis.
226 case OMPD_parallel_for:
227 case OMPD_parallel_for_simd:
228 case OMPD_parallel_sections:
235 case OMPD_target_data: {
237 // Parse directive name of the 'critical' directive if any.
238 if (DKind == OMPD_critical) {
239 BalancedDelimiterTracker T(*this, tok::l_paren,
240 tok::annot_pragma_openmp_end);
241 if (!T.consumeOpen()) {
242 if (Tok.isAnyIdentifier()) {
244 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
247 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
251 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
252 CancelRegion = ParseOpenMPDirectiveKind(*this);
253 if (Tok.isNot(tok::annot_pragma_openmp_end))
257 if (isOpenMPLoopDirective(DKind))
258 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
259 if (isOpenMPSimdDirective(DKind))
260 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
261 ParseScope OMPDirectiveScope(this, ScopeFlags);
262 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
264 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
265 OpenMPClauseKind CKind =
268 : FlushHasClause ? OMPC_flush
269 : getOpenMPClauseKind(PP.getSpelling(Tok));
270 Actions.StartOpenMPClause(CKind);
271 FlushHasClause = false;
273 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
274 FirstClauses[CKind].setInt(true);
276 FirstClauses[CKind].setPointer(Clause);
277 Clauses.push_back(Clause);
281 if (Tok.is(tok::comma))
283 Actions.EndOpenMPClause();
285 // End location of the directive.
286 EndLoc = Tok.getLocation();
287 // Consume final annot_pragma_openmp_end.
290 StmtResult AssociatedStmt;
291 bool CreateDirective = true;
292 if (HasAssociatedStatement) {
293 // The body is a block scope like in Lambdas and Blocks.
294 Sema::CompoundScopeRAII CompoundScope(Actions);
295 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
296 Actions.ActOnStartOfCompoundStmt();
298 AssociatedStmt = ParseStatement();
299 Actions.ActOnFinishOfCompoundStmt();
300 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
301 CreateDirective = AssociatedStmt.isUsable();
304 Directive = Actions.ActOnOpenMPExecutableDirective(
305 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
309 Actions.EndOpenMPDSABlock(Directive.get());
310 OMPDirectiveScope.Exit();
314 Diag(Tok, diag::err_omp_unknown_directive);
315 SkipUntil(tok::annot_pragma_openmp_end);
321 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
324 /// simple-variable-list:
325 /// '(' id-expression {, id-expression} ')'
327 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
328 SmallVectorImpl<Expr *> &VarList,
329 bool AllowScopeSpecifier) {
332 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
333 if (T.expectAndConsume(diag::err_expected_lparen_after,
334 getOpenMPDirectiveName(Kind)))
336 bool IsCorrect = true;
337 bool NoIdentIsFound = true;
339 // Read tokens while ')' or annot_pragma_openmp_end is not found.
340 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
342 SourceLocation TemplateKWLoc;
346 NoIdentIsFound = false;
348 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
349 ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
351 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
353 } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
354 TemplateKWLoc, Name)) {
356 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
358 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
359 Tok.isNot(tok::annot_pragma_openmp_end)) {
361 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
363 Diag(PrevTok.getLocation(), diag::err_expected)
365 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
367 DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
369 Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
371 VarList.push_back(Res.get());
374 if (Tok.is(tok::comma)) {
379 if (NoIdentIsFound) {
380 Diag(Tok, diag::err_expected) << tok::identifier;
385 IsCorrect = !T.consumeClose() && IsCorrect;
387 return !IsCorrect && VarList.empty();
390 /// \brief Parsing of OpenMP clauses.
393 /// if-clause | final-clause | num_threads-clause | safelen-clause |
394 /// default-clause | private-clause | firstprivate-clause | shared-clause
395 /// | linear-clause | aligned-clause | collapse-clause |
396 /// lastprivate-clause | reduction-clause | proc_bind-clause |
397 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
398 /// mergeable-clause | flush-clause | read-clause | write-clause |
399 /// update-clause | capture-clause | seq_cst-clause | device-clause |
402 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
403 OpenMPClauseKind CKind, bool FirstClause) {
404 OMPClause *Clause = nullptr;
405 bool ErrorFound = false;
406 // Check if clause is allowed for the given directive.
407 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
408 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
409 << getOpenMPDirectiveName(DKind);
416 case OMPC_num_threads:
422 // OpenMP [2.5, Restrictions]
423 // At most one if clause can appear on the directive.
424 // At most one num_threads clause can appear on the directive.
425 // OpenMP [2.8.1, simd construct, Restrictions]
426 // Only one safelen clause can appear on a simd directive.
427 // Only one simdlen clause can appear on a simd directive.
428 // Only one collapse clause can appear on a simd directive.
429 // OpenMP [2.9.1, target data construct, Restrictions]
430 // At most one device clause can appear on the directive.
431 // OpenMP [2.11.1, task Construct, Restrictions]
432 // At most one if clause can appear on the directive.
433 // At most one final clause can appear on the directive.
435 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
436 << getOpenMPClauseName(CKind);
440 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
441 Clause = ParseOpenMPClause(CKind);
443 Clause = ParseOpenMPSingleExprClause(CKind);
447 // OpenMP [2.14.3.1, Restrictions]
448 // Only a single default clause may be specified on a parallel, task or
450 // OpenMP [2.5, parallel Construct, Restrictions]
451 // At most one proc_bind clause can appear on the directive.
453 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
454 << getOpenMPClauseName(CKind);
458 Clause = ParseOpenMPSimpleClause(CKind);
461 // OpenMP [2.7.1, Restrictions, p. 3]
462 // Only one schedule clause can appear on a loop directive.
464 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
465 << getOpenMPClauseName(CKind);
469 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
479 // OpenMP [2.7.1, Restrictions, p. 9]
480 // Only one ordered clause can appear on a loop directive.
481 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
482 // Only one nowait clause can appear on a for directive.
484 Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
485 << getOpenMPClauseName(CKind);
489 Clause = ParseOpenMPClause(CKind);
492 case OMPC_firstprivate:
493 case OMPC_lastprivate:
499 case OMPC_copyprivate:
502 Clause = ParseOpenMPVarListClause(CKind);
505 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
506 << getOpenMPDirectiveName(DKind);
507 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
509 case OMPC_threadprivate:
510 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
511 << getOpenMPDirectiveName(DKind);
512 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
515 return ErrorFound ? nullptr : Clause;
518 /// \brief Parsing of OpenMP clauses with single expressions like 'if',
519 /// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
520 /// 'thread_limit' or 'simdlen'.
523 /// 'if' '(' expression ')'
526 /// 'final' '(' expression ')'
528 /// num_threads-clause:
529 /// 'num_threads' '(' expression ')'
532 /// 'safelen' '(' expression ')'
535 /// 'simdlen' '(' expression ')'
538 /// 'collapse' '(' expression ')'
540 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
541 SourceLocation Loc = ConsumeToken();
543 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
544 if (T.expectAndConsume(diag::err_expected_lparen_after,
545 getOpenMPClauseName(Kind)))
548 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
549 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
557 return Actions.ActOnOpenMPSingleExprClause(
558 Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
561 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
564 /// 'default' '(' 'none' | 'shared' ')
566 /// proc_bind-clause:
567 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
569 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
570 SourceLocation Loc = Tok.getLocation();
571 SourceLocation LOpen = ConsumeToken();
573 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
574 if (T.expectAndConsume(diag::err_expected_lparen_after,
575 getOpenMPClauseName(Kind)))
578 unsigned Type = getOpenMPSimpleClauseType(
579 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
580 SourceLocation TypeLoc = Tok.getLocation();
581 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
582 Tok.isNot(tok::annot_pragma_openmp_end))
588 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
592 /// \brief Parsing of OpenMP clauses like 'ordered'.
603 /// mergeable-clause:
609 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
610 SourceLocation Loc = Tok.getLocation();
613 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
617 /// \brief Parsing of OpenMP clauses with single expressions and some additional
618 /// argument like 'schedule' or 'dist_schedule'.
621 /// 'schedule' '(' kind [',' expression ] ')'
623 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
624 SourceLocation Loc = ConsumeToken();
625 SourceLocation CommaLoc;
627 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
628 if (T.expectAndConsume(diag::err_expected_lparen_after,
629 getOpenMPClauseName(Kind)))
633 unsigned Type = getOpenMPSimpleClauseType(
634 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
635 SourceLocation KLoc = Tok.getLocation();
636 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
637 Tok.isNot(tok::annot_pragma_openmp_end))
640 if (Kind == OMPC_schedule &&
641 (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
642 Type == OMPC_SCHEDULE_guided) &&
643 Tok.is(tok::comma)) {
644 CommaLoc = ConsumeAnyToken();
645 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
646 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
654 return Actions.ActOnOpenMPSingleExprWithArgClause(
655 Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
656 T.getCloseLocation());
659 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
660 UnqualifiedId &ReductionId) {
661 SourceLocation TemplateKWLoc;
662 if (ReductionIdScopeSpec.isEmpty()) {
664 switch (P.getCurToken().getKind()) {
692 if (OOK != OO_None) {
693 SourceLocation OpLoc = P.ConsumeToken();
694 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
695 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
699 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
700 /*AllowDestructorName*/ false,
701 /*AllowConstructorName*/ false, ParsedType(),
702 TemplateKWLoc, ReductionId);
705 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
706 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
709 /// 'private' '(' list ')'
710 /// firstprivate-clause:
711 /// 'firstprivate' '(' list ')'
712 /// lastprivate-clause:
713 /// 'lastprivate' '(' list ')'
715 /// 'shared' '(' list ')'
717 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
719 /// 'aligned' '(' list [ ':' alignment ] ')'
720 /// reduction-clause:
721 /// 'reduction' '(' reduction-identifier ':' list ')'
722 /// copyprivate-clause:
723 /// 'copyprivate' '(' list ')'
725 /// 'flush' '(' list ')'
727 /// 'depend' '(' in | out | inout : list ')'
729 /// For 'linear' clause linear-list may have the following forms:
732 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
733 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
734 SourceLocation Loc = Tok.getLocation();
735 SourceLocation LOpen = ConsumeToken();
736 SourceLocation ColonLoc = SourceLocation();
737 // Optional scope specifier and unqualified id for reduction identifier.
738 CXXScopeSpec ReductionIdScopeSpec;
739 UnqualifiedId ReductionId;
740 bool InvalidReductionId = false;
741 OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
742 // OpenMP 4.1 [2.15.3.7, linear Clause]
743 // If no modifier is specified it is assumed to be val.
744 OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val;
745 SourceLocation DepLinLoc;
748 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
749 if (T.expectAndConsume(diag::err_expected_lparen_after,
750 getOpenMPClauseName(Kind)))
753 bool NeedRParenForLinear = false;
754 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
755 tok::annot_pragma_openmp_end);
756 // Handle reduction-identifier for reduction clause.
757 if (Kind == OMPC_reduction) {
758 ColonProtectionRAIIObject ColonRAII(*this);
759 if (getLangOpts().CPlusPlus) {
760 ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
763 ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
764 if (InvalidReductionId) {
765 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
768 if (Tok.is(tok::colon)) {
769 ColonLoc = ConsumeToken();
771 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
773 } else if (Kind == OMPC_depend) {
774 // Handle dependency type for depend clause.
775 ColonProtectionRAIIObject ColonRAII(*this);
776 DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
777 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
778 DepLinLoc = Tok.getLocation();
780 if (DepKind == OMPC_DEPEND_unknown) {
781 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
786 if (Tok.is(tok::colon)) {
787 ColonLoc = ConsumeToken();
789 Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
791 } else if (Kind == OMPC_linear) {
792 // Try to parse modifier if any.
793 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
794 LinearModifier = static_cast<OpenMPLinearClauseKind>(
795 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
796 DepLinLoc = ConsumeToken();
797 LinearT.consumeOpen();
798 NeedRParenForLinear = true;
802 SmallVector<Expr *, 5> Vars;
803 bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
804 ((Kind == OMPC_reduction) && !InvalidReductionId) ||
805 ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
806 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
807 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
808 Tok.isNot(tok::annot_pragma_openmp_end))) {
809 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
812 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
813 if (VarExpr.isUsable()) {
814 Vars.push_back(VarExpr.get());
816 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
820 IsComma = Tok.is(tok::comma);
823 else if (Tok.isNot(tok::r_paren) &&
824 Tok.isNot(tok::annot_pragma_openmp_end) &&
825 (!MayHaveTail || Tok.isNot(tok::colon)))
826 Diag(Tok, diag::err_omp_expected_punc)
827 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
828 : getOpenMPClauseName(Kind))
829 << (Kind == OMPC_flush);
832 // Parse ')' for linear clause with modifier.
833 if (NeedRParenForLinear)
834 LinearT.consumeClose();
836 // Parse ':' linear-step (or ':' alignment).
837 Expr *TailExpr = nullptr;
838 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
840 ColonLoc = Tok.getLocation();
843 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
845 TailExpr = Tail.get();
847 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
853 if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
854 (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
858 return Actions.ActOnOpenMPVarListClause(
859 Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
860 ReductionIdScopeSpec,
861 ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
862 : DeclarationNameInfo(),
863 DepKind, LinearModifier, DepLinLoc);