1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 /// This file implements parsing of all OpenMP directives and clauses.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/StmtOpenMP.h"
15 #include "clang/Parse/ParseDiagnostic.h"
16 #include "clang/Parse/Parser.h"
17 #include "clang/Parse/RAIIObjectsForParser.h"
18 #include "clang/Sema/Scope.h"
19 #include "llvm/ADT/PointerIntPair.h"
21 using namespace clang;
23 //===----------------------------------------------------------------------===//
24 // OpenMP declarative directives.
25 //===----------------------------------------------------------------------===//
28 enum OpenMPDirectiveKindEx {
29 OMPD_cancellation = OMPD_unknown + 1,
41 OMPD_distribute_parallel,
42 OMPD_teams_distribute_parallel,
43 OMPD_target_teams_distribute_parallel,
47 class DeclDirectiveListParserHelper final {
48 SmallVector<Expr *, 4> Identifiers;
50 OpenMPDirectiveKind Kind;
53 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
55 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
56 ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
57 P->getCurScope(), SS, NameInfo, Kind);
59 Identifiers.push_back(Res.get());
61 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
65 // Map token string to extended OMP token kind that are
66 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
67 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
68 auto DKind = getOpenMPDirectiveKind(S);
69 if (DKind != OMPD_unknown)
72 return llvm::StringSwitch<unsigned>(S)
73 .Case("cancellation", OMPD_cancellation)
74 .Case("data", OMPD_data)
75 .Case("declare", OMPD_declare)
76 .Case("end", OMPD_end)
77 .Case("enter", OMPD_enter)
78 .Case("exit", OMPD_exit)
79 .Case("point", OMPD_point)
80 .Case("reduction", OMPD_reduction)
81 .Case("update", OMPD_update)
82 .Case("mapper", OMPD_mapper)
83 .Default(OMPD_unknown);
86 static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
87 // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
88 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
89 // TODO: add other combined directives in topological order.
90 static const unsigned F[][3] = {
91 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
92 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
93 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
94 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
95 {OMPD_declare, OMPD_target, OMPD_declare_target},
96 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
97 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
98 {OMPD_distribute_parallel_for, OMPD_simd,
99 OMPD_distribute_parallel_for_simd},
100 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
101 {OMPD_end, OMPD_declare, OMPD_end_declare},
102 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
103 {OMPD_target, OMPD_data, OMPD_target_data},
104 {OMPD_target, OMPD_enter, OMPD_target_enter},
105 {OMPD_target, OMPD_exit, OMPD_target_exit},
106 {OMPD_target, OMPD_update, OMPD_target_update},
107 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
108 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
109 {OMPD_for, OMPD_simd, OMPD_for_simd},
110 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
111 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
112 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
113 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
114 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
115 {OMPD_target, OMPD_simd, OMPD_target_simd},
116 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
117 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
118 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
119 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
120 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
121 {OMPD_teams_distribute_parallel, OMPD_for,
122 OMPD_teams_distribute_parallel_for},
123 {OMPD_teams_distribute_parallel_for, OMPD_simd,
124 OMPD_teams_distribute_parallel_for_simd},
125 {OMPD_target, OMPD_teams, OMPD_target_teams},
126 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
127 {OMPD_target_teams_distribute, OMPD_parallel,
128 OMPD_target_teams_distribute_parallel},
129 {OMPD_target_teams_distribute, OMPD_simd,
130 OMPD_target_teams_distribute_simd},
131 {OMPD_target_teams_distribute_parallel, OMPD_for,
132 OMPD_target_teams_distribute_parallel_for},
133 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
134 OMPD_target_teams_distribute_parallel_for_simd}};
135 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
136 Token Tok = P.getCurToken();
139 ? static_cast<unsigned>(OMPD_unknown)
140 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
141 if (DKind == OMPD_unknown)
144 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
145 if (DKind != F[I][0])
148 Tok = P.getPreprocessor().LookAhead(0);
151 ? static_cast<unsigned>(OMPD_unknown)
152 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
153 if (SDKind == OMPD_unknown)
156 if (SDKind == F[I][1]) {
161 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
165 static DeclarationName parseOpenMPReductionId(Parser &P) {
166 Token Tok = P.getCurToken();
167 Sema &Actions = P.getActions();
168 OverloadedOperatorKind OOK = OO_None;
169 // Allow to use 'operator' keyword for C++ operators
170 bool WithOperator = false;
171 if (Tok.is(tok::kw_operator)) {
173 Tok = P.getCurToken();
176 switch (Tok.getKind()) {
177 case tok::plus: // '+'
180 case tok::minus: // '-'
183 case tok::star: // '*'
186 case tok::amp: // '&'
189 case tok::pipe: // '|'
192 case tok::caret: // '^'
195 case tok::ampamp: // '&&'
198 case tok::pipepipe: // '||'
201 case tok::identifier: // identifier
206 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
207 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
208 Parser::StopBeforeMatch);
209 return DeclarationName();
212 auto &DeclNames = Actions.getASTContext().DeclarationNames;
213 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
214 : DeclNames.getCXXOperatorName(OOK);
217 /// Parse 'omp declare reduction' construct.
219 /// declare-reduction-directive:
220 /// annot_pragma_openmp 'declare' 'reduction'
221 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
222 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
223 /// annot_pragma_openmp_end
224 /// <reduction_id> is either a base language identifier or one of the following
225 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
227 Parser::DeclGroupPtrTy
228 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
230 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
231 if (T.expectAndConsume(diag::err_expected_lparen_after,
232 getOpenMPDirectiveName(OMPD_declare_reduction))) {
233 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
234 return DeclGroupPtrTy();
237 DeclarationName Name = parseOpenMPReductionId(*this);
238 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
239 return DeclGroupPtrTy();
242 bool IsCorrect = !ExpectAndConsume(tok::colon);
244 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
245 return DeclGroupPtrTy();
247 IsCorrect = IsCorrect && !Name.isEmpty();
249 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
250 Diag(Tok.getLocation(), diag::err_expected_type);
254 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
255 return DeclGroupPtrTy();
257 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
258 // Parse list of types until ':' token.
260 ColonProtectionRAIIObject ColonRAII(*this);
263 ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
265 QualType ReductionType =
266 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
267 if (!ReductionType.isNull()) {
268 ReductionTypes.push_back(
269 std::make_pair(ReductionType, Range.getBegin()));
272 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
276 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
280 if (ExpectAndConsume(tok::comma)) {
282 if (Tok.is(tok::annot_pragma_openmp_end)) {
283 Diag(Tok.getLocation(), diag::err_expected_type);
284 return DeclGroupPtrTy();
287 } while (Tok.isNot(tok::annot_pragma_openmp_end));
289 if (ReductionTypes.empty()) {
290 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
291 return DeclGroupPtrTy();
294 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
295 return DeclGroupPtrTy();
298 if (ExpectAndConsume(tok::colon))
301 if (Tok.is(tok::annot_pragma_openmp_end)) {
302 Diag(Tok.getLocation(), diag::err_expected_expression);
303 return DeclGroupPtrTy();
306 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
307 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
309 // Parse <combiner> expression and then parse initializer if any for each
311 unsigned I = 0, E = ReductionTypes.size();
312 for (Decl *D : DRD.get()) {
313 TentativeParsingAction TPA(*this);
314 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
315 Scope::CompoundStmtScope |
316 Scope::OpenMPDirectiveScope);
317 // Parse <combiner> expression.
318 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
319 ExprResult CombinerResult =
320 Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
321 D->getLocation(), /*DiscardedValue*/ false);
322 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
324 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
325 Tok.isNot(tok::annot_pragma_openmp_end)) {
330 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
331 ExprResult InitializerResult;
332 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
333 // Parse <initializer> expression.
334 if (Tok.is(tok::identifier) &&
335 Tok.getIdentifierInfo()->isStr("initializer")) {
338 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
344 BalancedDelimiterTracker T(*this, tok::l_paren,
345 tok::annot_pragma_openmp_end);
347 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
349 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
350 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
351 Scope::CompoundStmtScope |
352 Scope::OpenMPDirectiveScope);
354 VarDecl *OmpPrivParm =
355 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
357 // Check if initializer is omp_priv <init_expr> or something else.
358 if (Tok.is(tok::identifier) &&
359 Tok.getIdentifierInfo()->isStr("omp_priv")) {
360 if (Actions.getLangOpts().CPlusPlus) {
361 InitializerResult = Actions.ActOnFinishFullExpr(
362 ParseAssignmentExpression().get(), D->getLocation(),
363 /*DiscardedValue*/ false);
366 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
369 InitializerResult = Actions.ActOnFinishFullExpr(
370 ParseAssignmentExpression().get(), D->getLocation(),
371 /*DiscardedValue*/ false);
373 Actions.ActOnOpenMPDeclareReductionInitializerEnd(
374 D, InitializerResult.get(), OmpPrivParm);
375 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
376 Tok.isNot(tok::annot_pragma_openmp_end)) {
382 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
387 // Revert parsing if not the last type, otherwise accept it, we're done with
394 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
398 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
399 // Parse declarator '=' initializer.
400 // If a '==' or '+=' is found, suggest a fixit to '='.
401 if (isTokenEqualOrEqualTypo()) {
404 if (Tok.is(tok::code_completion)) {
405 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
406 Actions.FinalizeDeclaration(OmpPrivParm);
411 ExprResult Init(ParseInitializer());
413 if (Init.isInvalid()) {
414 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
415 Actions.ActOnInitializerError(OmpPrivParm);
417 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
418 /*DirectInit=*/false);
420 } else if (Tok.is(tok::l_paren)) {
421 // Parse C++ direct initializer: '(' expression-list ')'
422 BalancedDelimiterTracker T(*this, tok::l_paren);
426 CommaLocsTy CommaLocs;
428 SourceLocation LParLoc = T.getOpenLocation();
429 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
430 QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
431 getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
432 OmpPrivParm->getLocation(), Exprs, LParLoc);
433 CalledSignatureHelp = true;
434 return PreferredType;
436 if (ParseExpressionList(Exprs, CommaLocs, [&] {
437 PreferredType.enterFunctionArgument(Tok.getLocation(),
440 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
442 Actions.ActOnInitializerError(OmpPrivParm);
443 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
446 SourceLocation RLoc = Tok.getLocation();
447 if (!T.consumeClose())
448 RLoc = T.getCloseLocation();
450 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
451 "Unexpected number of commas!");
453 ExprResult Initializer =
454 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
455 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
456 /*DirectInit=*/true);
458 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
459 // Parse C++0x braced-init-list.
460 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
462 ExprResult Init(ParseBraceInitializer());
464 if (Init.isInvalid()) {
465 Actions.ActOnInitializerError(OmpPrivParm);
467 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
468 /*DirectInit=*/true);
471 Actions.ActOnUninitializedDecl(OmpPrivParm);
475 /// Parses 'omp declare mapper' directive.
477 /// declare-mapper-directive:
478 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
479 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
480 /// annot_pragma_openmp_end
481 /// <mapper-identifier> and <var> are base language identifiers.
483 Parser::DeclGroupPtrTy
484 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
485 bool IsCorrect = true;
487 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
488 if (T.expectAndConsume(diag::err_expected_lparen_after,
489 getOpenMPDirectiveName(OMPD_declare_mapper))) {
490 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
491 return DeclGroupPtrTy();
494 // Parse <mapper-identifier>
495 auto &DeclNames = Actions.getASTContext().DeclarationNames;
496 DeclarationName MapperId;
497 if (PP.LookAhead(0).is(tok::colon)) {
498 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
499 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
502 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
506 ExpectAndConsume(tok::colon);
508 // If no mapper identifier is provided, its name is "default" by default
510 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
513 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
514 return DeclGroupPtrTy();
516 // Parse <type> <var>
517 DeclarationName VName;
520 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
521 if (ParsedType.isUsable())
523 Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
524 if (MapperType.isNull())
527 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
528 return DeclGroupPtrTy();
532 IsCorrect &= !T.consumeClose();
534 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
535 return DeclGroupPtrTy();
539 OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
540 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
541 Range.getBegin(), VName, AS);
542 DeclarationNameInfo DirName;
543 SourceLocation Loc = Tok.getLocation();
544 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
545 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
546 ParseScope OMPDirectiveScope(this, ScopeFlags);
547 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
549 // Add the mapper variable declaration.
550 Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
551 DMD, getCurScope(), MapperType, Range.getBegin(), VName);
553 // Parse map clauses.
554 SmallVector<OMPClause *, 6> Clauses;
555 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
556 OpenMPClauseKind CKind = Tok.isAnnotation()
558 : getOpenMPClauseKind(PP.getSpelling(Tok));
559 Actions.StartOpenMPClause(CKind);
561 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
563 Clauses.push_back(Clause);
567 if (Tok.is(tok::comma))
569 Actions.EndOpenMPClause();
571 if (Clauses.empty()) {
572 Diag(Tok, diag::err_omp_expected_clause)
573 << getOpenMPDirectiveName(OMPD_declare_mapper);
578 Actions.EndOpenMPDSABlock(nullptr);
579 OMPDirectiveScope.Exit();
582 Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
584 return DeclGroupPtrTy();
588 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
589 DeclarationName &Name,
590 AccessSpecifier AS) {
591 // Parse the common declaration-specifiers piece.
592 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
593 DeclSpec DS(AttrFactory);
594 ParseSpecifierQualifierList(DS, AS, DSC);
596 // Parse the declarator.
597 DeclaratorContext Context = DeclaratorContext::PrototypeContext;
598 Declarator DeclaratorInfo(DS, Context);
599 ParseDeclarator(DeclaratorInfo);
600 Range = DeclaratorInfo.getSourceRange();
601 if (DeclaratorInfo.getIdentifier() == nullptr) {
602 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
605 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
607 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
611 /// RAII that recreates function context for correct parsing of clauses of
612 /// 'declare simd' construct.
613 /// OpenMP, 2.8.2 declare simd Construct
614 /// The expressions appearing in the clauses of this directive are evaluated in
615 /// the scope of the arguments of the function declaration or definition.
616 class FNContextRAII final {
618 Sema::CXXThisScopeRAII *ThisScope;
619 Parser::ParseScope *TempScope;
620 Parser::ParseScope *FnScope;
621 bool HasTemplateScope = false;
622 bool HasFunScope = false;
623 FNContextRAII() = delete;
624 FNContextRAII(const FNContextRAII &) = delete;
625 FNContextRAII &operator=(const FNContextRAII &) = delete;
628 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
629 Decl *D = *Ptr.get().begin();
630 NamedDecl *ND = dyn_cast<NamedDecl>(D);
631 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
632 Sema &Actions = P.getActions();
634 // Allow 'this' within late-parsed attributes.
635 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
636 ND && ND->isCXXInstanceMember());
638 // If the Decl is templatized, add template parameters to scope.
639 HasTemplateScope = D->isTemplateDecl();
641 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
642 if (HasTemplateScope)
643 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
645 // If the Decl is on a function, add function parameters to the scope.
646 HasFunScope = D->isFunctionOrFunctionTemplate();
647 FnScope = new Parser::ParseScope(
648 &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
651 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
655 P.getActions().ActOnExitFunctionContext();
656 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
658 if (HasTemplateScope)
667 /// Parses clauses for 'declare simd' directive.
669 /// 'inbranch' | 'notinbranch'
670 /// 'simdlen' '(' <expr> ')'
671 /// { 'uniform' '(' <argument_list> ')' }
672 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
673 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
674 static bool parseDeclareSimdClauses(
675 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
676 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
677 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
678 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
680 const Token &Tok = P.getCurToken();
681 bool IsError = false;
682 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
683 if (Tok.isNot(tok::identifier))
685 OMPDeclareSimdDeclAttr::BranchStateTy Out;
686 IdentifierInfo *II = Tok.getIdentifierInfo();
687 StringRef ClauseName = II->getName();
688 // Parse 'inranch|notinbranch' clauses.
689 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
690 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
691 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
693 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
697 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
699 } else if (ClauseName.equals("simdlen")) {
700 if (SimdLen.isUsable()) {
701 P.Diag(Tok, diag::err_omp_more_one_clause)
702 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
707 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
708 if (SimdLen.isInvalid())
711 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
712 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
713 CKind == OMPC_linear) {
714 Parser::OpenMPVarListDataTy Data;
715 SmallVectorImpl<Expr *> *Vars = &Uniforms;
716 if (CKind == OMPC_aligned)
718 else if (CKind == OMPC_linear)
722 if (P.ParseOpenMPVarList(OMPD_declare_simd,
723 getOpenMPClauseKind(ClauseName), *Vars, Data))
725 if (CKind == OMPC_aligned) {
726 Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
727 } else if (CKind == OMPC_linear) {
728 if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
730 Data.LinKind = OMPC_LINEAR_val;
731 LinModifiers.append(Linears.size() - LinModifiers.size(),
733 Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
736 // TODO: add parsing of other clauses.
740 if (Tok.is(tok::comma))
746 /// Parse clauses for '#pragma omp declare simd'.
747 Parser::DeclGroupPtrTy
748 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
749 CachedTokens &Toks, SourceLocation Loc) {
750 PP.EnterToken(Tok, /*IsReinject*/ true);
751 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
752 /*IsReinject*/ true);
753 // Consume the previously pushed token.
754 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
756 FNContextRAII FnContext(*this, Ptr);
757 OMPDeclareSimdDeclAttr::BranchStateTy BS =
758 OMPDeclareSimdDeclAttr::BS_Undefined;
760 SmallVector<Expr *, 4> Uniforms;
761 SmallVector<Expr *, 4> Aligneds;
762 SmallVector<Expr *, 4> Alignments;
763 SmallVector<Expr *, 4> Linears;
764 SmallVector<unsigned, 4> LinModifiers;
765 SmallVector<Expr *, 4> Steps;
767 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
768 Alignments, Linears, LinModifiers, Steps);
769 // Need to check for extra tokens.
770 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
771 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
772 << getOpenMPDirectiveName(OMPD_declare_simd);
773 while (Tok.isNot(tok::annot_pragma_openmp_end))
776 // Skip the last annot_pragma_openmp_end.
777 SourceLocation EndLoc = ConsumeAnnotationToken();
780 return Actions.ActOnOpenMPDeclareSimdDirective(
781 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
782 LinModifiers, Steps, SourceRange(Loc, EndLoc));
785 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
786 // OpenMP 4.5 syntax with list of entities.
787 Sema::NamedDeclSetType SameDirectiveDecls;
788 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
789 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
790 if (Tok.is(tok::identifier)) {
791 IdentifierInfo *II = Tok.getIdentifierInfo();
792 StringRef ClauseName = II->getName();
793 // Parse 'to|link' clauses.
794 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) {
795 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName;
800 auto &&Callback = [this, MT, &SameDirectiveDecls](
801 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
802 Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
805 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
806 /*AllowScopeSpecifier=*/true))
809 // Consume optional ','.
810 if (Tok.is(tok::comma))
813 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
815 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
816 SameDirectiveDecls.end());
818 return DeclGroupPtrTy();
819 return Actions.BuildDeclaratorGroup(Decls);
822 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
823 SourceLocation DTLoc) {
824 if (DKind != OMPD_end_declare_target) {
825 Diag(Tok, diag::err_expected_end_declare_target);
826 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
830 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
831 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
832 << getOpenMPDirectiveName(OMPD_end_declare_target);
833 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
835 // Skip the last annot_pragma_openmp_end.
839 /// Parsing of declarative OpenMP directives.
841 /// threadprivate-directive:
842 /// annot_pragma_openmp 'threadprivate' simple-variable-list
843 /// annot_pragma_openmp_end
845 /// allocate-directive:
846 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
847 /// annot_pragma_openmp_end
849 /// declare-reduction-directive:
850 /// annot_pragma_openmp 'declare' 'reduction' [...]
851 /// annot_pragma_openmp_end
853 /// declare-mapper-directive:
854 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
855 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
856 /// annot_pragma_openmp_end
858 /// declare-simd-directive:
859 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
860 /// annot_pragma_openmp_end
861 /// <function declaration/definition>
863 /// requires directive:
864 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
865 /// annot_pragma_openmp_end
867 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
868 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
869 DeclSpec::TST TagType, Decl *Tag) {
870 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
871 ParenBraceBracketBalancer BalancerRAIIObj(*this);
873 SourceLocation Loc = ConsumeAnnotationToken();
874 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
877 case OMPD_threadprivate: {
879 DeclDirectiveListParserHelper Helper(this, DKind);
880 if (!ParseOpenMPSimpleVarList(DKind, Helper,
881 /*AllowScopeSpecifier=*/true)) {
882 // The last seen token is annot_pragma_openmp_end - need to check for
884 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
885 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
886 << getOpenMPDirectiveName(DKind);
887 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
889 // Skip the last annot_pragma_openmp_end.
890 ConsumeAnnotationToken();
891 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
892 Helper.getIdentifiers());
896 case OMPD_allocate: {
898 DeclDirectiveListParserHelper Helper(this, DKind);
899 if (!ParseOpenMPSimpleVarList(DKind, Helper,
900 /*AllowScopeSpecifier=*/true)) {
901 SmallVector<OMPClause *, 1> Clauses;
902 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
903 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
905 FirstClauses(OMPC_unknown + 1);
906 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
907 OpenMPClauseKind CKind =
908 Tok.isAnnotation() ? OMPC_unknown
909 : getOpenMPClauseKind(PP.getSpelling(Tok));
910 Actions.StartOpenMPClause(CKind);
911 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
912 !FirstClauses[CKind].getInt());
913 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
915 FirstClauses[CKind].setInt(true);
916 if (Clause != nullptr)
917 Clauses.push_back(Clause);
918 if (Tok.is(tok::annot_pragma_openmp_end)) {
919 Actions.EndOpenMPClause();
923 if (Tok.is(tok::comma))
925 Actions.EndOpenMPClause();
927 // The last seen token is annot_pragma_openmp_end - need to check for
929 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
930 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
931 << getOpenMPDirectiveName(DKind);
932 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
935 // Skip the last annot_pragma_openmp_end.
936 ConsumeAnnotationToken();
937 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
942 case OMPD_requires: {
943 SourceLocation StartLoc = ConsumeToken();
944 SmallVector<OMPClause *, 5> Clauses;
945 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
946 FirstClauses(OMPC_unknown + 1);
947 if (Tok.is(tok::annot_pragma_openmp_end)) {
948 Diag(Tok, diag::err_omp_expected_clause)
949 << getOpenMPDirectiveName(OMPD_requires);
952 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
953 OpenMPClauseKind CKind = Tok.isAnnotation()
955 : getOpenMPClauseKind(PP.getSpelling(Tok));
956 Actions.StartOpenMPClause(CKind);
957 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
958 !FirstClauses[CKind].getInt());
959 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
961 FirstClauses[CKind].setInt(true);
962 if (Clause != nullptr)
963 Clauses.push_back(Clause);
964 if (Tok.is(tok::annot_pragma_openmp_end)) {
965 Actions.EndOpenMPClause();
969 if (Tok.is(tok::comma))
971 Actions.EndOpenMPClause();
973 // Consume final annot_pragma_openmp_end
974 if (Clauses.size() == 0) {
975 Diag(Tok, diag::err_omp_expected_clause)
976 << getOpenMPDirectiveName(OMPD_requires);
977 ConsumeAnnotationToken();
980 ConsumeAnnotationToken();
981 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
983 case OMPD_declare_reduction:
985 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
986 // The last seen token is annot_pragma_openmp_end - need to check for
988 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
989 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
990 << getOpenMPDirectiveName(OMPD_declare_reduction);
991 while (Tok.isNot(tok::annot_pragma_openmp_end))
994 // Skip the last annot_pragma_openmp_end.
995 ConsumeAnnotationToken();
999 case OMPD_declare_mapper: {
1001 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1002 // Skip the last annot_pragma_openmp_end.
1003 ConsumeAnnotationToken();
1008 case OMPD_declare_simd: {
1010 // { #pragma omp declare simd }
1011 // <function-declaration-or-definition>
1015 while(Tok.isNot(tok::annot_pragma_openmp_end)) {
1016 Toks.push_back(Tok);
1019 Toks.push_back(Tok);
1023 if (Tok.is(tok::annot_pragma_openmp)) {
1024 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
1025 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1026 // Here we expect to see some function declaration.
1027 if (AS == AS_none) {
1028 assert(TagType == DeclSpec::TST_unspecified);
1029 MaybeParseCXX11Attributes(Attrs);
1030 ParsingDeclSpec PDS(*this);
1031 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1034 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1038 Diag(Loc, diag::err_omp_decl_in_declare_simd);
1039 return DeclGroupPtrTy();
1041 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1043 case OMPD_declare_target: {
1044 SourceLocation DTLoc = ConsumeAnyToken();
1045 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1046 return ParseOMPDeclareTargetClauses();
1049 // Skip the last annot_pragma_openmp_end.
1052 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1053 return DeclGroupPtrTy();
1055 llvm::SmallVector<Decl *, 4> Decls;
1056 DKind = parseOpenMPDirectiveKind(*this);
1057 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1058 Tok.isNot(tok::r_brace)) {
1060 // Here we expect to see some function declaration.
1061 if (AS == AS_none) {
1062 assert(TagType == DeclSpec::TST_unspecified);
1063 MaybeParseCXX11Attributes(Attrs);
1064 ParsingDeclSpec PDS(*this);
1065 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1068 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1071 DeclGroupRef Ref = Ptr.get();
1072 Decls.append(Ref.begin(), Ref.end());
1074 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
1075 TentativeParsingAction TPA(*this);
1076 ConsumeAnnotationToken();
1077 DKind = parseOpenMPDirectiveKind(*this);
1078 if (DKind != OMPD_end_declare_target)
1085 ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1086 Actions.ActOnFinishOpenMPDeclareTargetDirective();
1087 return Actions.BuildDeclaratorGroup(Decls);
1090 Diag(Tok, diag::err_omp_unknown_directive);
1095 case OMPD_taskyield:
1098 case OMPD_taskgroup:
1108 case OMPD_parallel_for:
1109 case OMPD_parallel_for_simd:
1110 case OMPD_parallel_sections:
1114 case OMPD_cancellation_point:
1116 case OMPD_target_data:
1117 case OMPD_target_enter_data:
1118 case OMPD_target_exit_data:
1119 case OMPD_target_parallel:
1120 case OMPD_target_parallel_for:
1122 case OMPD_taskloop_simd:
1123 case OMPD_distribute:
1124 case OMPD_end_declare_target:
1125 case OMPD_target_update:
1126 case OMPD_distribute_parallel_for:
1127 case OMPD_distribute_parallel_for_simd:
1128 case OMPD_distribute_simd:
1129 case OMPD_target_parallel_for_simd:
1130 case OMPD_target_simd:
1131 case OMPD_teams_distribute:
1132 case OMPD_teams_distribute_simd:
1133 case OMPD_teams_distribute_parallel_for_simd:
1134 case OMPD_teams_distribute_parallel_for:
1135 case OMPD_target_teams:
1136 case OMPD_target_teams_distribute:
1137 case OMPD_target_teams_distribute_parallel_for:
1138 case OMPD_target_teams_distribute_parallel_for_simd:
1139 case OMPD_target_teams_distribute_simd:
1140 Diag(Tok, diag::err_omp_unexpected_directive)
1141 << 1 << getOpenMPDirectiveName(DKind);
1144 while (Tok.isNot(tok::annot_pragma_openmp_end))
1150 /// Parsing of declarative or executable OpenMP directives.
1152 /// threadprivate-directive:
1153 /// annot_pragma_openmp 'threadprivate' simple-variable-list
1154 /// annot_pragma_openmp_end
1156 /// allocate-directive:
1157 /// annot_pragma_openmp 'allocate' simple-variable-list
1158 /// annot_pragma_openmp_end
1160 /// declare-reduction-directive:
1161 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
1162 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
1163 /// ('omp_priv' '=' <expression>|<function_call>) ')']
1164 /// annot_pragma_openmp_end
1166 /// declare-mapper-directive:
1167 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1168 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
1169 /// annot_pragma_openmp_end
1171 /// executable-directive:
1172 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
1173 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
1174 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
1175 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
1176 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
1177 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
1178 /// 'distribute' | 'target enter data' | 'target exit data' |
1179 /// 'target parallel' | 'target parallel for' |
1180 /// 'target update' | 'distribute parallel for' |
1181 /// 'distribute paralle for simd' | 'distribute simd' |
1182 /// 'target parallel for simd' | 'target simd' |
1183 /// 'teams distribute' | 'teams distribute simd' |
1184 /// 'teams distribute parallel for simd' |
1185 /// 'teams distribute parallel for' | 'target teams' |
1186 /// 'target teams distribute' |
1187 /// 'target teams distribute parallel for' |
1188 /// 'target teams distribute parallel for simd' |
1189 /// 'target teams distribute simd' {clause}
1190 /// annot_pragma_openmp_end
1193 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1194 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1195 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1196 SmallVector<OMPClause *, 5> Clauses;
1197 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
1198 FirstClauses(OMPC_unknown + 1);
1199 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
1200 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
1201 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
1202 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
1203 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
1204 // Name of critical directive.
1205 DeclarationNameInfo DirName;
1206 StmtResult Directive = StmtError();
1207 bool HasAssociatedStatement = true;
1208 bool FlushHasClause = false;
1211 case OMPD_threadprivate: {
1212 // FIXME: Should this be permitted in C++?
1213 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1214 ParsedStmtContext()) {
1215 Diag(Tok, diag::err_omp_immediate_directive)
1216 << getOpenMPDirectiveName(DKind) << 0;
1219 DeclDirectiveListParserHelper Helper(this, DKind);
1220 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1221 /*AllowScopeSpecifier=*/false)) {
1222 // The last seen token is annot_pragma_openmp_end - need to check for
1224 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1225 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1226 << getOpenMPDirectiveName(DKind);
1227 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1229 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
1230 Loc, Helper.getIdentifiers());
1231 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1233 SkipUntil(tok::annot_pragma_openmp_end);
1236 case OMPD_allocate: {
1237 // FIXME: Should this be permitted in C++?
1238 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1239 ParsedStmtContext()) {
1240 Diag(Tok, diag::err_omp_immediate_directive)
1241 << getOpenMPDirectiveName(DKind) << 0;
1244 DeclDirectiveListParserHelper Helper(this, DKind);
1245 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1246 /*AllowScopeSpecifier=*/false)) {
1247 SmallVector<OMPClause *, 1> Clauses;
1248 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1249 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1251 FirstClauses(OMPC_unknown + 1);
1252 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1253 OpenMPClauseKind CKind =
1254 Tok.isAnnotation() ? OMPC_unknown
1255 : getOpenMPClauseKind(PP.getSpelling(Tok));
1256 Actions.StartOpenMPClause(CKind);
1257 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1258 !FirstClauses[CKind].getInt());
1259 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1261 FirstClauses[CKind].setInt(true);
1262 if (Clause != nullptr)
1263 Clauses.push_back(Clause);
1264 if (Tok.is(tok::annot_pragma_openmp_end)) {
1265 Actions.EndOpenMPClause();
1269 if (Tok.is(tok::comma))
1271 Actions.EndOpenMPClause();
1273 // The last seen token is annot_pragma_openmp_end - need to check for
1275 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1276 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1277 << getOpenMPDirectiveName(DKind);
1278 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1281 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
1282 Loc, Helper.getIdentifiers(), Clauses);
1283 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1285 SkipUntil(tok::annot_pragma_openmp_end);
1288 case OMPD_declare_reduction:
1290 if (DeclGroupPtrTy Res =
1291 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
1292 // The last seen token is annot_pragma_openmp_end - need to check for
1294 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1295 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1296 << getOpenMPDirectiveName(OMPD_declare_reduction);
1297 while (Tok.isNot(tok::annot_pragma_openmp_end))
1301 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1303 SkipUntil(tok::annot_pragma_openmp_end);
1306 case OMPD_declare_mapper: {
1308 if (DeclGroupPtrTy Res =
1309 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
1310 // Skip the last annot_pragma_openmp_end.
1311 ConsumeAnnotationToken();
1312 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1314 SkipUntil(tok::annot_pragma_openmp_end);
1319 if (PP.LookAhead(0).is(tok::l_paren)) {
1320 FlushHasClause = true;
1321 // Push copy of the current token back to stream to properly parse
1322 // pseudo-clause OMPFlushClause.
1323 PP.EnterToken(Tok, /*IsReinject*/ true);
1326 case OMPD_taskyield:
1329 case OMPD_cancellation_point:
1331 case OMPD_target_enter_data:
1332 case OMPD_target_exit_data:
1333 case OMPD_target_update:
1334 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1335 ParsedStmtContext()) {
1336 Diag(Tok, diag::err_omp_immediate_directive)
1337 << getOpenMPDirectiveName(DKind) << 0;
1339 HasAssociatedStatement = false;
1340 // Fall through for further analysis.
1351 case OMPD_parallel_for:
1352 case OMPD_parallel_for_simd:
1353 case OMPD_parallel_sections:
1359 case OMPD_taskgroup:
1360 case OMPD_target_data:
1361 case OMPD_target_parallel:
1362 case OMPD_target_parallel_for:
1364 case OMPD_taskloop_simd:
1365 case OMPD_distribute:
1366 case OMPD_distribute_parallel_for:
1367 case OMPD_distribute_parallel_for_simd:
1368 case OMPD_distribute_simd:
1369 case OMPD_target_parallel_for_simd:
1370 case OMPD_target_simd:
1371 case OMPD_teams_distribute:
1372 case OMPD_teams_distribute_simd:
1373 case OMPD_teams_distribute_parallel_for_simd:
1374 case OMPD_teams_distribute_parallel_for:
1375 case OMPD_target_teams:
1376 case OMPD_target_teams_distribute:
1377 case OMPD_target_teams_distribute_parallel_for:
1378 case OMPD_target_teams_distribute_parallel_for_simd:
1379 case OMPD_target_teams_distribute_simd: {
1381 // Parse directive name of the 'critical' directive if any.
1382 if (DKind == OMPD_critical) {
1383 BalancedDelimiterTracker T(*this, tok::l_paren,
1384 tok::annot_pragma_openmp_end);
1385 if (!T.consumeOpen()) {
1386 if (Tok.isAnyIdentifier()) {
1388 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1391 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1395 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1396 CancelRegion = parseOpenMPDirectiveKind(*this);
1397 if (Tok.isNot(tok::annot_pragma_openmp_end))
1401 if (isOpenMPLoopDirective(DKind))
1402 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1403 if (isOpenMPSimdDirective(DKind))
1404 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1405 ParseScope OMPDirectiveScope(this, ScopeFlags);
1406 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1408 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1409 OpenMPClauseKind CKind =
1412 : FlushHasClause ? OMPC_flush
1413 : getOpenMPClauseKind(PP.getSpelling(Tok));
1414 Actions.StartOpenMPClause(CKind);
1415 FlushHasClause = false;
1417 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1418 FirstClauses[CKind].setInt(true);
1420 FirstClauses[CKind].setPointer(Clause);
1421 Clauses.push_back(Clause);
1425 if (Tok.is(tok::comma))
1427 Actions.EndOpenMPClause();
1429 // End location of the directive.
1430 EndLoc = Tok.getLocation();
1431 // Consume final annot_pragma_openmp_end.
1432 ConsumeAnnotationToken();
1434 // OpenMP [2.13.8, ordered Construct, Syntax]
1435 // If the depend clause is specified, the ordered construct is a stand-alone
1437 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1438 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1439 ParsedStmtContext()) {
1440 Diag(Loc, diag::err_omp_immediate_directive)
1441 << getOpenMPDirectiveName(DKind) << 1
1442 << getOpenMPClauseName(OMPC_depend);
1444 HasAssociatedStatement = false;
1447 StmtResult AssociatedStmt;
1448 if (HasAssociatedStatement) {
1449 // The body is a block scope like in Lambdas and Blocks.
1450 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1451 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
1452 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
1453 // should have at least one compound statement scope within it.
1454 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
1455 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1456 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1457 DKind == OMPD_target_exit_data) {
1458 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1459 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
1460 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
1461 /*isStmtExpr=*/false));
1462 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1464 Directive = Actions.ActOnOpenMPExecutableDirective(
1465 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1469 Actions.EndOpenMPDSABlock(Directive.get());
1470 OMPDirectiveScope.Exit();
1473 case OMPD_declare_simd:
1474 case OMPD_declare_target:
1475 case OMPD_end_declare_target:
1477 Diag(Tok, diag::err_omp_unexpected_directive)
1478 << 1 << getOpenMPDirectiveName(DKind);
1479 SkipUntil(tok::annot_pragma_openmp_end);
1482 Diag(Tok, diag::err_omp_unknown_directive);
1483 SkipUntil(tok::annot_pragma_openmp_end);
1489 // Parses simple list:
1490 // simple-variable-list:
1491 // '(' id-expression {, id-expression} ')'
1493 bool Parser::ParseOpenMPSimpleVarList(
1494 OpenMPDirectiveKind Kind,
1495 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1497 bool AllowScopeSpecifier) {
1499 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1500 if (T.expectAndConsume(diag::err_expected_lparen_after,
1501 getOpenMPDirectiveName(Kind)))
1503 bool IsCorrect = true;
1504 bool NoIdentIsFound = true;
1506 // Read tokens while ')' or annot_pragma_openmp_end is not found.
1507 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1511 Token PrevTok = Tok;
1512 NoIdentIsFound = false;
1514 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1515 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1517 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1519 } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1522 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1524 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1525 Tok.isNot(tok::annot_pragma_openmp_end)) {
1527 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1529 Diag(PrevTok.getLocation(), diag::err_expected)
1531 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1533 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1536 if (Tok.is(tok::comma)) {
1541 if (NoIdentIsFound) {
1542 Diag(Tok, diag::err_expected) << tok::identifier;
1547 IsCorrect = !T.consumeClose() && IsCorrect;
1552 /// Parsing of OpenMP clauses.
1555 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1556 /// default-clause | private-clause | firstprivate-clause | shared-clause
1557 /// | linear-clause | aligned-clause | collapse-clause |
1558 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1559 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1560 /// mergeable-clause | flush-clause | read-clause | write-clause |
1561 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1562 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1563 /// thread_limit-clause | priority-clause | grainsize-clause |
1564 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1565 /// from-clause | is_device_ptr-clause | task_reduction-clause |
1566 /// in_reduction-clause | allocator-clause | allocate-clause
1568 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1569 OpenMPClauseKind CKind, bool FirstClause) {
1570 OMPClause *Clause = nullptr;
1571 bool ErrorFound = false;
1572 bool WrongDirective = false;
1573 // Check if clause is allowed for the given directive.
1574 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1575 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1576 << getOpenMPDirectiveName(DKind);
1578 WrongDirective = true;
1583 case OMPC_num_threads:
1589 case OMPC_num_teams:
1590 case OMPC_thread_limit:
1592 case OMPC_grainsize:
1593 case OMPC_num_tasks:
1595 case OMPC_allocator:
1596 // OpenMP [2.5, Restrictions]
1597 // At most one num_threads clause can appear on the directive.
1598 // OpenMP [2.8.1, simd construct, Restrictions]
1599 // Only one safelen clause can appear on a simd directive.
1600 // Only one simdlen clause can appear on a simd directive.
1601 // Only one collapse clause can appear on a simd directive.
1602 // OpenMP [2.9.1, target data construct, Restrictions]
1603 // At most one device clause can appear on the directive.
1604 // OpenMP [2.11.1, task Construct, Restrictions]
1605 // At most one if clause can appear on the directive.
1606 // At most one final clause can appear on the directive.
1607 // OpenMP [teams Construct, Restrictions]
1608 // At most one num_teams clause can appear on the directive.
1609 // At most one thread_limit clause can appear on the directive.
1610 // OpenMP [2.9.1, task Construct, Restrictions]
1611 // At most one priority clause can appear on the directive.
1612 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1613 // At most one grainsize clause can appear on the directive.
1614 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1615 // At most one num_tasks clause can appear on the directive.
1616 // OpenMP [2.11.3, allocate Directive, Restrictions]
1617 // At most one allocator clause can appear on the directive.
1619 Diag(Tok, diag::err_omp_more_one_clause)
1620 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1624 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1625 Clause = ParseOpenMPClause(CKind, WrongDirective);
1627 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
1630 case OMPC_proc_bind:
1631 case OMPC_atomic_default_mem_order:
1632 // OpenMP [2.14.3.1, Restrictions]
1633 // Only a single default clause may be specified on a parallel, task or
1635 // OpenMP [2.5, parallel Construct, Restrictions]
1636 // At most one proc_bind clause can appear on the directive.
1637 // OpenMP [5.0, Requires directive, Restrictions]
1638 // At most one atomic_default_mem_order clause can appear
1641 Diag(Tok, diag::err_omp_more_one_clause)
1642 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1646 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
1649 case OMPC_dist_schedule:
1650 case OMPC_defaultmap:
1651 // OpenMP [2.7.1, Restrictions, p. 3]
1652 // Only one schedule clause can appear on a loop directive.
1653 // OpenMP [2.10.4, Restrictions, p. 106]
1654 // At most one defaultmap clause can appear on the directive.
1656 Diag(Tok, diag::err_omp_more_one_clause)
1657 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1663 Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
1667 case OMPC_mergeable:
1676 case OMPC_unified_address:
1677 case OMPC_unified_shared_memory:
1678 case OMPC_reverse_offload:
1679 case OMPC_dynamic_allocators:
1680 // OpenMP [2.7.1, Restrictions, p. 9]
1681 // Only one ordered clause can appear on a loop directive.
1682 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1683 // Only one nowait clause can appear on a for directive.
1684 // OpenMP [5.0, Requires directive, Restrictions]
1685 // Each of the requires clauses can appear at most once on the directive.
1687 Diag(Tok, diag::err_omp_more_one_clause)
1688 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1692 Clause = ParseOpenMPClause(CKind, WrongDirective);
1695 case OMPC_firstprivate:
1696 case OMPC_lastprivate:
1698 case OMPC_reduction:
1699 case OMPC_task_reduction:
1700 case OMPC_in_reduction:
1704 case OMPC_copyprivate:
1710 case OMPC_use_device_ptr:
1711 case OMPC_is_device_ptr:
1713 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
1716 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1717 << getOpenMPDirectiveName(DKind);
1718 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1720 case OMPC_threadprivate:
1722 if (!WrongDirective)
1723 Diag(Tok, diag::err_omp_unexpected_clause)
1724 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
1725 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1728 return ErrorFound ? nullptr : Clause;
1731 /// Parses simple expression in parens for single-expression clauses of OpenMP
1733 /// \param RLoc Returned location of right paren.
1734 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
1735 SourceLocation &RLoc) {
1736 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1737 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1740 SourceLocation ELoc = Tok.getLocation();
1741 ExprResult LHS(ParseCastExpression(
1742 /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1743 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1744 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
1747 RLoc = Tok.getLocation();
1748 if (!T.consumeClose())
1749 RLoc = T.getCloseLocation();
1754 /// Parsing of OpenMP clauses with single expressions like 'final',
1755 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1756 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1759 /// 'final' '(' expression ')'
1761 /// num_threads-clause:
1762 /// 'num_threads' '(' expression ')'
1765 /// 'safelen' '(' expression ')'
1768 /// 'simdlen' '(' expression ')'
1770 /// collapse-clause:
1771 /// 'collapse' '(' expression ')'
1773 /// priority-clause:
1774 /// 'priority' '(' expression ')'
1776 /// grainsize-clause:
1777 /// 'grainsize' '(' expression ')'
1779 /// num_tasks-clause:
1780 /// 'num_tasks' '(' expression ')'
1783 /// 'hint' '(' expression ')'
1785 /// allocator-clause:
1786 /// 'allocator' '(' expression ')'
1788 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
1790 SourceLocation Loc = ConsumeToken();
1791 SourceLocation LLoc = Tok.getLocation();
1792 SourceLocation RLoc;
1794 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1796 if (Val.isInvalid())
1801 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1804 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1807 /// 'default' '(' 'none' | 'shared' ')
1809 /// proc_bind-clause:
1810 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1812 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
1814 SourceLocation Loc = Tok.getLocation();
1815 SourceLocation LOpen = ConsumeToken();
1817 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1818 if (T.expectAndConsume(diag::err_expected_lparen_after,
1819 getOpenMPClauseName(Kind)))
1822 unsigned Type = getOpenMPSimpleClauseType(
1823 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1824 SourceLocation TypeLoc = Tok.getLocation();
1825 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1826 Tok.isNot(tok::annot_pragma_openmp_end))
1830 SourceLocation RLoc = Tok.getLocation();
1831 if (!T.consumeClose())
1832 RLoc = T.getCloseLocation();
1836 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
1839 /// Parsing of OpenMP clauses like 'ordered'.
1850 /// mergeable-clause:
1865 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
1866 SourceLocation Loc = Tok.getLocation();
1871 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1875 /// Parsing of OpenMP clauses with single expressions and some additional
1876 /// argument like 'schedule' or 'dist_schedule'.
1878 /// schedule-clause:
1879 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1883 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1886 /// 'defaultmap' '(' modifier ':' kind ')'
1888 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
1890 SourceLocation Loc = ConsumeToken();
1891 SourceLocation DelimLoc;
1893 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1894 if (T.expectAndConsume(diag::err_expected_lparen_after,
1895 getOpenMPClauseName(Kind)))
1899 SmallVector<unsigned, 4> Arg;
1900 SmallVector<SourceLocation, 4> KLoc;
1901 if (Kind == OMPC_schedule) {
1902 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1903 Arg.resize(NumberOfElements);
1904 KLoc.resize(NumberOfElements);
1905 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1906 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1907 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1908 unsigned KindModifier = getOpenMPSimpleClauseType(
1909 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1910 if (KindModifier > OMPC_SCHEDULE_unknown) {
1912 Arg[Modifier1] = KindModifier;
1913 KLoc[Modifier1] = Tok.getLocation();
1914 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1915 Tok.isNot(tok::annot_pragma_openmp_end))
1917 if (Tok.is(tok::comma)) {
1918 // Parse ',' 'modifier'
1920 KindModifier = getOpenMPSimpleClauseType(
1921 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1922 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1924 : (unsigned)OMPC_SCHEDULE_unknown;
1925 KLoc[Modifier2] = Tok.getLocation();
1926 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1927 Tok.isNot(tok::annot_pragma_openmp_end))
1931 if (Tok.is(tok::colon))
1934 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1935 KindModifier = getOpenMPSimpleClauseType(
1936 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1938 Arg[ScheduleKind] = KindModifier;
1939 KLoc[ScheduleKind] = Tok.getLocation();
1940 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1941 Tok.isNot(tok::annot_pragma_openmp_end))
1943 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1944 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1945 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1947 DelimLoc = ConsumeAnyToken();
1948 } else if (Kind == OMPC_dist_schedule) {
1949 Arg.push_back(getOpenMPSimpleClauseType(
1950 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1951 KLoc.push_back(Tok.getLocation());
1952 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1953 Tok.isNot(tok::annot_pragma_openmp_end))
1955 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1956 DelimLoc = ConsumeAnyToken();
1957 } else if (Kind == OMPC_defaultmap) {
1958 // Get a defaultmap modifier
1959 Arg.push_back(getOpenMPSimpleClauseType(
1960 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1961 KLoc.push_back(Tok.getLocation());
1962 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1963 Tok.isNot(tok::annot_pragma_openmp_end))
1966 if (Tok.is(tok::colon))
1968 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1969 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1970 // Get a defaultmap kind
1971 Arg.push_back(getOpenMPSimpleClauseType(
1972 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1973 KLoc.push_back(Tok.getLocation());
1974 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1975 Tok.isNot(tok::annot_pragma_openmp_end))
1978 assert(Kind == OMPC_if);
1979 KLoc.push_back(Tok.getLocation());
1980 TentativeParsingAction TPA(*this);
1981 Arg.push_back(parseOpenMPDirectiveKind(*this));
1982 if (Arg.back() != OMPD_unknown) {
1984 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1986 DelimLoc = ConsumeToken();
1989 Arg.back() = OMPD_unknown;
1996 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1997 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1999 if (NeedAnExpression) {
2000 SourceLocation ELoc = Tok.getLocation();
2001 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
2002 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
2004 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2008 SourceLocation RLoc = Tok.getLocation();
2009 if (!T.consumeClose())
2010 RLoc = T.getCloseLocation();
2012 if (NeedAnExpression && Val.isInvalid())
2017 return Actions.ActOnOpenMPSingleExprWithArgClause(
2018 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
2021 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
2022 UnqualifiedId &ReductionId) {
2023 if (ReductionIdScopeSpec.isEmpty()) {
2025 switch (P.getCurToken().getKind()) {
2053 if (OOK != OO_None) {
2054 SourceLocation OpLoc = P.ConsumeToken();
2055 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
2056 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
2060 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
2061 /*AllowDestructorName*/ false,
2062 /*AllowConstructorName*/ false,
2063 /*AllowDeductionGuide*/ false,
2064 nullptr, nullptr, ReductionId);
2067 /// Checks if the token is a valid map-type-modifier.
2068 static OpenMPMapModifierKind isMapModifier(Parser &P) {
2069 Token Tok = P.getCurToken();
2070 if (!Tok.is(tok::identifier))
2071 return OMPC_MAP_MODIFIER_unknown;
2073 Preprocessor &PP = P.getPreprocessor();
2074 OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
2075 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2076 return TypeModifier;
2079 /// Parse the mapper modifier in map, to, and from clauses.
2080 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
2082 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
2083 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
2084 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2088 // Parse mapper-identifier
2089 if (getLangOpts().CPlusPlus)
2090 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2091 /*ObjectType=*/nullptr,
2092 /*EnteringContext=*/false);
2093 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
2094 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
2095 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2099 auto &DeclNames = Actions.getASTContext().DeclarationNames;
2100 Data.ReductionOrMapperId = DeclarationNameInfo(
2101 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
2104 return T.consumeClose();
2107 /// Parse map-type-modifiers in map clause.
2108 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2109 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
2110 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
2111 while (getCurToken().isNot(tok::colon)) {
2112 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
2113 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
2114 TypeModifier == OMPC_MAP_MODIFIER_close) {
2115 Data.MapTypeModifiers.push_back(TypeModifier);
2116 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2118 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
2119 Data.MapTypeModifiers.push_back(TypeModifier);
2120 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2122 if (parseMapperModifier(Data))
2125 // For the case of unknown map-type-modifier or a map-type.
2126 // Map-type is followed by a colon; the function returns when it
2127 // encounters a token followed by a colon.
2128 if (Tok.is(tok::comma)) {
2129 Diag(Tok, diag::err_omp_map_type_modifier_missing);
2133 // Potential map-type token as it is followed by a colon.
2134 if (PP.LookAhead(0).is(tok::colon))
2136 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
2139 if (getCurToken().is(tok::comma))
2145 /// Checks if the token is a valid map-type.
2146 static OpenMPMapClauseKind isMapType(Parser &P) {
2147 Token Tok = P.getCurToken();
2148 // The map-type token can be either an identifier or the C++ delete keyword.
2149 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
2150 return OMPC_MAP_unknown;
2151 Preprocessor &PP = P.getPreprocessor();
2152 OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
2153 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2157 /// Parse map-type in map clause.
2158 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2159 /// where, map-type ::= to | from | tofrom | alloc | release | delete
2160 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
2161 Token Tok = P.getCurToken();
2162 if (Tok.is(tok::colon)) {
2163 P.Diag(Tok, diag::err_omp_map_type_missing);
2166 Data.MapType = isMapType(P);
2167 if (Data.MapType == OMPC_MAP_unknown)
2168 P.Diag(Tok, diag::err_omp_unknown_map_type);
2172 /// Parses clauses with list.
2173 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
2174 OpenMPClauseKind Kind,
2175 SmallVectorImpl<Expr *> &Vars,
2176 OpenMPVarListDataTy &Data) {
2177 UnqualifiedId UnqualifiedReductionId;
2178 bool InvalidReductionId = false;
2179 bool IsInvalidMapperModifier = false;
2182 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2183 if (T.expectAndConsume(diag::err_expected_lparen_after,
2184 getOpenMPClauseName(Kind)))
2187 bool NeedRParenForLinear = false;
2188 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
2189 tok::annot_pragma_openmp_end);
2190 // Handle reduction-identifier for reduction clause.
2191 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
2192 Kind == OMPC_in_reduction) {
2193 ColonProtectionRAIIObject ColonRAII(*this);
2194 if (getLangOpts().CPlusPlus)
2195 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2196 /*ObjectType=*/nullptr,
2197 /*EnteringContext=*/false);
2198 InvalidReductionId = ParseReductionId(
2199 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
2200 if (InvalidReductionId) {
2201 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2204 if (Tok.is(tok::colon))
2205 Data.ColonLoc = ConsumeToken();
2207 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
2208 if (!InvalidReductionId)
2209 Data.ReductionOrMapperId =
2210 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
2211 } else if (Kind == OMPC_depend) {
2212 // Handle dependency type for depend clause.
2213 ColonProtectionRAIIObject ColonRAII(*this);
2215 static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
2216 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
2217 Data.DepLinMapLoc = Tok.getLocation();
2219 if (Data.DepKind == OMPC_DEPEND_unknown) {
2220 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2224 // Special processing for depend(source) clause.
2225 if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
2231 if (Tok.is(tok::colon)) {
2232 Data.ColonLoc = ConsumeToken();
2234 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
2235 : diag::warn_pragma_expected_colon)
2236 << "dependency type";
2238 } else if (Kind == OMPC_linear) {
2239 // Try to parse modifier if any.
2240 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
2241 Data.LinKind = static_cast<OpenMPLinearClauseKind>(
2242 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2243 Data.DepLinMapLoc = ConsumeToken();
2244 LinearT.consumeOpen();
2245 NeedRParenForLinear = true;
2247 } else if (Kind == OMPC_map) {
2248 // Handle map type for map clause.
2249 ColonProtectionRAIIObject ColonRAII(*this);
2251 // The first identifier may be a list item, a map-type or a
2252 // map-type-modifier. The map-type can also be delete which has the same
2253 // spelling of the C++ delete keyword.
2254 Data.DepLinMapLoc = Tok.getLocation();
2256 // Check for presence of a colon in the map clause.
2257 TentativeParsingAction TPA(*this);
2258 bool ColonPresent = false;
2259 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2261 if (Tok.is(tok::colon))
2262 ColonPresent = true;
2265 // Only parse map-type-modifier[s] and map-type if a colon is present in
2268 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
2269 if (!IsInvalidMapperModifier)
2270 parseMapType(*this, Data);
2272 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
2274 if (Data.MapType == OMPC_MAP_unknown) {
2275 Data.MapType = OMPC_MAP_tofrom;
2276 Data.IsMapTypeImplicit = true;
2279 if (Tok.is(tok::colon))
2280 Data.ColonLoc = ConsumeToken();
2281 } else if (Kind == OMPC_to || Kind == OMPC_from) {
2282 if (Tok.is(tok::identifier)) {
2283 bool IsMapperModifier = false;
2284 if (Kind == OMPC_to) {
2285 auto Modifier = static_cast<OpenMPToModifierKind>(
2286 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2287 if (Modifier == OMPC_TO_MODIFIER_mapper)
2288 IsMapperModifier = true;
2290 auto Modifier = static_cast<OpenMPFromModifierKind>(
2291 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2292 if (Modifier == OMPC_FROM_MODIFIER_mapper)
2293 IsMapperModifier = true;
2295 if (IsMapperModifier) {
2296 // Parse the mapper modifier.
2298 IsInvalidMapperModifier = parseMapperModifier(Data);
2299 if (Tok.isNot(tok::colon)) {
2300 if (!IsInvalidMapperModifier)
2301 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
2302 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2306 if (Tok.is(tok::colon))
2310 } else if (Kind == OMPC_allocate) {
2311 // Handle optional allocator expression followed by colon delimiter.
2312 ColonProtectionRAIIObject ColonRAII(*this);
2313 TentativeParsingAction TPA(*this);
2315 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2316 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
2317 /*DiscardedValue=*/false);
2318 if (Tail.isUsable()) {
2319 if (Tok.is(tok::colon)) {
2320 Data.TailExpr = Tail.get();
2321 Data.ColonLoc = ConsumeToken();
2324 // colon not found, no allocator specified, parse only list of
2329 // Parsing was unsuccessfull, revert and skip to the end of clause or
2332 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2338 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
2339 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
2340 (Kind == OMPC_reduction && !InvalidReductionId) ||
2341 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
2342 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
2343 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
2344 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
2345 Tok.isNot(tok::annot_pragma_openmp_end))) {
2346 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
2348 ExprResult VarExpr =
2349 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2350 if (VarExpr.isUsable()) {
2351 Vars.push_back(VarExpr.get());
2353 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2357 IsComma = Tok.is(tok::comma);
2360 else if (Tok.isNot(tok::r_paren) &&
2361 Tok.isNot(tok::annot_pragma_openmp_end) &&
2362 (!MayHaveTail || Tok.isNot(tok::colon)))
2363 Diag(Tok, diag::err_omp_expected_punc)
2364 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
2365 : getOpenMPClauseName(Kind))
2366 << (Kind == OMPC_flush);
2369 // Parse ')' for linear clause with modifier.
2370 if (NeedRParenForLinear)
2371 LinearT.consumeClose();
2373 // Parse ':' linear-step (or ':' alignment).
2374 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
2376 Data.ColonLoc = Tok.getLocation();
2377 SourceLocation ELoc = ConsumeToken();
2378 ExprResult Tail = ParseAssignmentExpression();
2380 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
2381 if (Tail.isUsable())
2382 Data.TailExpr = Tail.get();
2384 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2389 Data.RLoc = Tok.getLocation();
2390 if (!T.consumeClose())
2391 Data.RLoc = T.getCloseLocation();
2392 return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
2394 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
2395 (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
2396 IsInvalidMapperModifier;
2399 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
2400 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
2404 /// 'private' '(' list ')'
2405 /// firstprivate-clause:
2406 /// 'firstprivate' '(' list ')'
2407 /// lastprivate-clause:
2408 /// 'lastprivate' '(' list ')'
2410 /// 'shared' '(' list ')'
2412 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
2414 /// 'aligned' '(' list [ ':' alignment ] ')'
2415 /// reduction-clause:
2416 /// 'reduction' '(' reduction-identifier ':' list ')'
2417 /// task_reduction-clause:
2418 /// 'task_reduction' '(' reduction-identifier ':' list ')'
2419 /// in_reduction-clause:
2420 /// 'in_reduction' '(' reduction-identifier ':' list ')'
2421 /// copyprivate-clause:
2422 /// 'copyprivate' '(' list ')'
2424 /// 'flush' '(' list ')'
2426 /// 'depend' '(' in | out | inout : list | source ')'
2428 /// 'map' '(' [ [ always [,] ] [ close [,] ]
2429 /// [ mapper '(' mapper-identifier ')' [,] ]
2430 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
2432 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2434 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2435 /// use_device_ptr-clause:
2436 /// 'use_device_ptr' '(' list ')'
2437 /// is_device_ptr-clause:
2438 /// 'is_device_ptr' '(' list ')'
2439 /// allocate-clause:
2440 /// 'allocate' '(' [ allocator ':' ] list ')'
2442 /// For 'linear' clause linear-list may have the following forms:
2445 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
2446 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
2447 OpenMPClauseKind Kind,
2449 SourceLocation Loc = Tok.getLocation();
2450 SourceLocation LOpen = ConsumeToken();
2451 SmallVector<Expr *, 4> Vars;
2452 OpenMPVarListDataTy Data;
2454 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
2459 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
2460 return Actions.ActOnOpenMPVarListClause(
2461 Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
2462 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind,
2463 Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
2464 Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc);