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 "clang/AST/ASTContext.h"
15 #include "clang/AST/StmtOpenMP.h"
16 #include "clang/Parse/ParseDiagnostic.h"
17 #include "clang/Parse/Parser.h"
18 #include "clang/Parse/RAIIObjectsForParser.h"
19 #include "clang/Sema/Scope.h"
20 #include "llvm/ADT/PointerIntPair.h"
22 using namespace clang;
24 //===----------------------------------------------------------------------===//
25 // OpenMP declarative directives.
26 //===----------------------------------------------------------------------===//
29 enum OpenMPDirectiveKindEx {
30 OMPD_cancellation = OMPD_unknown + 1,
42 OMPD_distribute_parallel,
43 OMPD_teams_distribute_parallel,
44 OMPD_target_teams_distribute_parallel
47 class ThreadprivateListParserHelper final {
48 SmallVector<Expr *, 4> Identifiers;
52 ThreadprivateListParserHelper(Parser *P) : P(P) {}
53 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
55 P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
57 Identifiers.push_back(Res.get());
59 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
63 // Map token string to extended OMP token kind that are
64 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
65 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
66 auto DKind = getOpenMPDirectiveKind(S);
67 if (DKind != OMPD_unknown)
70 return llvm::StringSwitch<unsigned>(S)
71 .Case("cancellation", OMPD_cancellation)
72 .Case("data", OMPD_data)
73 .Case("declare", OMPD_declare)
74 .Case("end", OMPD_end)
75 .Case("enter", OMPD_enter)
76 .Case("exit", OMPD_exit)
77 .Case("point", OMPD_point)
78 .Case("reduction", OMPD_reduction)
79 .Case("update", OMPD_update)
80 .Default(OMPD_unknown);
83 static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
84 // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
85 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
86 // TODO: add other combined directives in topological order.
87 static const unsigned F[][3] = {
88 { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
89 { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
90 { OMPD_declare, OMPD_simd, OMPD_declare_simd },
91 { OMPD_declare, OMPD_target, OMPD_declare_target },
92 { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
93 { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
94 { OMPD_distribute_parallel_for, OMPD_simd,
95 OMPD_distribute_parallel_for_simd },
96 { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
97 { OMPD_end, OMPD_declare, OMPD_end_declare },
98 { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
99 { OMPD_target, OMPD_data, OMPD_target_data },
100 { OMPD_target, OMPD_enter, OMPD_target_enter },
101 { OMPD_target, OMPD_exit, OMPD_target_exit },
102 { OMPD_target, OMPD_update, OMPD_target_update },
103 { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
104 { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
105 { OMPD_for, OMPD_simd, OMPD_for_simd },
106 { OMPD_parallel, OMPD_for, OMPD_parallel_for },
107 { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
108 { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
109 { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
110 { OMPD_target, OMPD_parallel, OMPD_target_parallel },
111 { OMPD_target, OMPD_simd, OMPD_target_simd },
112 { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
113 { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
114 { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
115 { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
116 { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
117 { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
118 { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
119 { OMPD_target, OMPD_teams, OMPD_target_teams },
120 { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
121 { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
122 { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
123 { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
124 { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
126 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
127 auto Tok = P.getCurToken();
130 ? static_cast<unsigned>(OMPD_unknown)
131 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
132 if (DKind == OMPD_unknown)
135 for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
136 if (DKind != F[i][0])
139 Tok = P.getPreprocessor().LookAhead(0);
142 ? static_cast<unsigned>(OMPD_unknown)
143 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
144 if (SDKind == OMPD_unknown)
147 if (SDKind == F[i][1]) {
152 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
156 static DeclarationName parseOpenMPReductionId(Parser &P) {
157 Token Tok = P.getCurToken();
158 Sema &Actions = P.getActions();
159 OverloadedOperatorKind OOK = OO_None;
160 // Allow to use 'operator' keyword for C++ operators
161 bool WithOperator = false;
162 if (Tok.is(tok::kw_operator)) {
164 Tok = P.getCurToken();
167 switch (Tok.getKind()) {
168 case tok::plus: // '+'
171 case tok::minus: // '-'
174 case tok::star: // '*'
177 case tok::amp: // '&'
180 case tok::pipe: // '|'
183 case tok::caret: // '^'
186 case tok::ampamp: // '&&'
189 case tok::pipepipe: // '||'
192 case tok::identifier: // identifier
197 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
198 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
199 Parser::StopBeforeMatch);
200 return DeclarationName();
203 auto &DeclNames = Actions.getASTContext().DeclarationNames;
204 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
205 : DeclNames.getCXXOperatorName(OOK);
208 /// \brief Parse 'omp declare reduction' construct.
210 /// declare-reduction-directive:
211 /// annot_pragma_openmp 'declare' 'reduction'
212 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
213 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
214 /// annot_pragma_openmp_end
215 /// <reduction_id> is either a base language identifier or one of the following
216 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
218 Parser::DeclGroupPtrTy
219 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
221 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
222 if (T.expectAndConsume(diag::err_expected_lparen_after,
223 getOpenMPDirectiveName(OMPD_declare_reduction))) {
224 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
225 return DeclGroupPtrTy();
228 DeclarationName Name = parseOpenMPReductionId(*this);
229 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
230 return DeclGroupPtrTy();
233 bool IsCorrect = !ExpectAndConsume(tok::colon);
235 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
236 return DeclGroupPtrTy();
238 IsCorrect = IsCorrect && !Name.isEmpty();
240 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
241 Diag(Tok.getLocation(), diag::err_expected_type);
245 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
246 return DeclGroupPtrTy();
248 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
249 // Parse list of types until ':' token.
251 ColonProtectionRAIIObject ColonRAII(*this);
253 TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS);
256 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
257 if (!ReductionType.isNull()) {
258 ReductionTypes.push_back(
259 std::make_pair(ReductionType, Range.getBegin()));
262 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
266 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
270 if (ExpectAndConsume(tok::comma)) {
272 if (Tok.is(tok::annot_pragma_openmp_end)) {
273 Diag(Tok.getLocation(), diag::err_expected_type);
274 return DeclGroupPtrTy();
277 } while (Tok.isNot(tok::annot_pragma_openmp_end));
279 if (ReductionTypes.empty()) {
280 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
281 return DeclGroupPtrTy();
284 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
285 return DeclGroupPtrTy();
288 if (ExpectAndConsume(tok::colon))
291 if (Tok.is(tok::annot_pragma_openmp_end)) {
292 Diag(Tok.getLocation(), diag::err_expected_expression);
293 return DeclGroupPtrTy();
296 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
297 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
299 // Parse <combiner> expression and then parse initializer if any for each
301 unsigned I = 0, E = ReductionTypes.size();
302 for (auto *D : DRD.get()) {
303 TentativeParsingAction TPA(*this);
304 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
305 Scope::CompoundStmtScope |
306 Scope::OpenMPDirectiveScope);
307 // Parse <combiner> expression.
308 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
309 ExprResult CombinerResult =
310 Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
311 D->getLocation(), /*DiscardedValue=*/true);
312 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
314 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
315 Tok.isNot(tok::annot_pragma_openmp_end)) {
320 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
321 ExprResult InitializerResult;
322 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
323 // Parse <initializer> expression.
324 if (Tok.is(tok::identifier) &&
325 Tok.getIdentifierInfo()->isStr("initializer"))
328 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
334 BalancedDelimiterTracker T(*this, tok::l_paren,
335 tok::annot_pragma_openmp_end);
337 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
339 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
340 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
341 Scope::CompoundStmtScope |
342 Scope::OpenMPDirectiveScope);
344 VarDecl *OmpPrivParm =
345 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
347 // Check if initializer is omp_priv <init_expr> or something else.
348 if (Tok.is(tok::identifier) &&
349 Tok.getIdentifierInfo()->isStr("omp_priv")) {
351 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
353 InitializerResult = Actions.ActOnFinishFullExpr(
354 ParseAssignmentExpression().get(), D->getLocation(),
355 /*DiscardedValue=*/true);
357 Actions.ActOnOpenMPDeclareReductionInitializerEnd(
358 D, InitializerResult.get(), OmpPrivParm);
359 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
360 Tok.isNot(tok::annot_pragma_openmp_end)) {
366 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
371 // Revert parsing if not the last type, otherwise accept it, we're done with
378 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
382 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
383 // Parse declarator '=' initializer.
384 // If a '==' or '+=' is found, suggest a fixit to '='.
385 if (isTokenEqualOrEqualTypo()) {
388 if (Tok.is(tok::code_completion)) {
389 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
390 Actions.FinalizeDeclaration(OmpPrivParm);
395 ExprResult Init(ParseInitializer());
397 if (Init.isInvalid()) {
398 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
399 Actions.ActOnInitializerError(OmpPrivParm);
401 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
402 /*DirectInit=*/false);
404 } else if (Tok.is(tok::l_paren)) {
405 // Parse C++ direct initializer: '(' expression-list ')'
406 BalancedDelimiterTracker T(*this, tok::l_paren);
410 CommaLocsTy CommaLocs;
412 if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
413 Actions.CodeCompleteConstructor(
414 getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
415 OmpPrivParm->getLocation(), Exprs);
417 Actions.ActOnInitializerError(OmpPrivParm);
418 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
423 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
424 "Unexpected number of commas!");
426 ExprResult Initializer = Actions.ActOnParenListExpr(
427 T.getOpenLocation(), T.getCloseLocation(), Exprs);
428 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
429 /*DirectInit=*/true);
431 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
432 // Parse C++0x braced-init-list.
433 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
435 ExprResult Init(ParseBraceInitializer());
437 if (Init.isInvalid()) {
438 Actions.ActOnInitializerError(OmpPrivParm);
440 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
441 /*DirectInit=*/true);
444 Actions.ActOnUninitializedDecl(OmpPrivParm);
449 /// RAII that recreates function context for correct parsing of clauses of
450 /// 'declare simd' construct.
451 /// OpenMP, 2.8.2 declare simd Construct
452 /// The expressions appearing in the clauses of this directive are evaluated in
453 /// the scope of the arguments of the function declaration or definition.
454 class FNContextRAII final {
456 Sema::CXXThisScopeRAII *ThisScope;
457 Parser::ParseScope *TempScope;
458 Parser::ParseScope *FnScope;
459 bool HasTemplateScope = false;
460 bool HasFunScope = false;
461 FNContextRAII() = delete;
462 FNContextRAII(const FNContextRAII &) = delete;
463 FNContextRAII &operator=(const FNContextRAII &) = delete;
466 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
467 Decl *D = *Ptr.get().begin();
468 NamedDecl *ND = dyn_cast<NamedDecl>(D);
469 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
470 Sema &Actions = P.getActions();
472 // Allow 'this' within late-parsed attributes.
473 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
474 ND && ND->isCXXInstanceMember());
476 // If the Decl is templatized, add template parameters to scope.
477 HasTemplateScope = D->isTemplateDecl();
479 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
480 if (HasTemplateScope)
481 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
483 // If the Decl is on a function, add function parameters to the scope.
484 HasFunScope = D->isFunctionOrFunctionTemplate();
485 FnScope = new Parser::ParseScope(
486 &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
489 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
493 P.getActions().ActOnExitFunctionContext();
494 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
496 if (HasTemplateScope)
505 /// Parses clauses for 'declare simd' directive.
507 /// 'inbranch' | 'notinbranch'
508 /// 'simdlen' '(' <expr> ')'
509 /// { 'uniform' '(' <argument_list> ')' }
510 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
511 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
512 static bool parseDeclareSimdClauses(
513 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
514 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
515 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
516 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
518 const Token &Tok = P.getCurToken();
519 bool IsError = false;
520 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
521 if (Tok.isNot(tok::identifier))
523 OMPDeclareSimdDeclAttr::BranchStateTy Out;
524 IdentifierInfo *II = Tok.getIdentifierInfo();
525 StringRef ClauseName = II->getName();
526 // Parse 'inranch|notinbranch' clauses.
527 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
528 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
529 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
531 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
535 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
537 } else if (ClauseName.equals("simdlen")) {
538 if (SimdLen.isUsable()) {
539 P.Diag(Tok, diag::err_omp_more_one_clause)
540 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
545 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
546 if (SimdLen.isInvalid())
549 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
550 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
551 CKind == OMPC_linear) {
552 Parser::OpenMPVarListDataTy Data;
553 auto *Vars = &Uniforms;
554 if (CKind == OMPC_aligned)
556 else if (CKind == OMPC_linear)
560 if (P.ParseOpenMPVarList(OMPD_declare_simd,
561 getOpenMPClauseKind(ClauseName), *Vars, Data))
563 if (CKind == OMPC_aligned)
564 Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
565 else if (CKind == OMPC_linear) {
566 if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
568 Data.LinKind = OMPC_LINEAR_val;
569 LinModifiers.append(Linears.size() - LinModifiers.size(),
571 Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
574 // TODO: add parsing of other clauses.
578 if (Tok.is(tok::comma))
584 /// Parse clauses for '#pragma omp declare simd'.
585 Parser::DeclGroupPtrTy
586 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
587 CachedTokens &Toks, SourceLocation Loc) {
589 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
590 // Consume the previously pushed token.
591 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
593 FNContextRAII FnContext(*this, Ptr);
594 OMPDeclareSimdDeclAttr::BranchStateTy BS =
595 OMPDeclareSimdDeclAttr::BS_Undefined;
597 SmallVector<Expr *, 4> Uniforms;
598 SmallVector<Expr *, 4> Aligneds;
599 SmallVector<Expr *, 4> Alignments;
600 SmallVector<Expr *, 4> Linears;
601 SmallVector<unsigned, 4> LinModifiers;
602 SmallVector<Expr *, 4> Steps;
604 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
605 Alignments, Linears, LinModifiers, Steps);
606 // Need to check for extra tokens.
607 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
608 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
609 << getOpenMPDirectiveName(OMPD_declare_simd);
610 while (Tok.isNot(tok::annot_pragma_openmp_end))
613 // Skip the last annot_pragma_openmp_end.
614 SourceLocation EndLoc = ConsumeAnnotationToken();
616 return Actions.ActOnOpenMPDeclareSimdDirective(
617 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
618 LinModifiers, Steps, SourceRange(Loc, EndLoc));
623 /// \brief Parsing of declarative OpenMP directives.
625 /// threadprivate-directive:
626 /// annot_pragma_openmp 'threadprivate' simple-variable-list
627 /// annot_pragma_openmp_end
629 /// declare-reduction-directive:
630 /// annot_pragma_openmp 'declare' 'reduction' [...]
631 /// annot_pragma_openmp_end
633 /// declare-simd-directive:
634 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
635 /// annot_pragma_openmp_end
636 /// <function declaration/definition>
638 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
639 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
640 DeclSpec::TST TagType, Decl *Tag) {
641 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
642 ParenBraceBracketBalancer BalancerRAIIObj(*this);
644 SourceLocation Loc = ConsumeAnnotationToken();
645 auto DKind = ParseOpenMPDirectiveKind(*this);
648 case OMPD_threadprivate: {
650 ThreadprivateListParserHelper Helper(this);
651 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
652 // The last seen token is annot_pragma_openmp_end - need to check for
654 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
655 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
656 << getOpenMPDirectiveName(OMPD_threadprivate);
657 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
659 // Skip the last annot_pragma_openmp_end.
660 ConsumeAnnotationToken();
661 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
662 Helper.getIdentifiers());
666 case OMPD_declare_reduction:
668 if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
669 // The last seen token is annot_pragma_openmp_end - need to check for
671 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
672 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
673 << getOpenMPDirectiveName(OMPD_declare_reduction);
674 while (Tok.isNot(tok::annot_pragma_openmp_end))
677 // Skip the last annot_pragma_openmp_end.
678 ConsumeAnnotationToken();
682 case OMPD_declare_simd: {
684 // { #pragma omp declare simd }
685 // <function-declaration-or-definition>
689 while(Tok.isNot(tok::annot_pragma_openmp_end)) {
697 if (Tok.is(tok::annot_pragma_openmp))
698 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
699 else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
700 // Here we expect to see some function declaration.
702 assert(TagType == DeclSpec::TST_unspecified);
703 MaybeParseCXX11Attributes(Attrs);
704 ParsingDeclSpec PDS(*this);
705 Ptr = ParseExternalDeclaration(Attrs, &PDS);
708 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
712 Diag(Loc, diag::err_omp_decl_in_declare_simd);
713 return DeclGroupPtrTy();
715 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
717 case OMPD_declare_target: {
718 SourceLocation DTLoc = ConsumeAnyToken();
719 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
720 // OpenMP 4.5 syntax with list of entities.
721 llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
722 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
723 OMPDeclareTargetDeclAttr::MapTypeTy MT =
724 OMPDeclareTargetDeclAttr::MT_To;
725 if (Tok.is(tok::identifier)) {
726 IdentifierInfo *II = Tok.getIdentifierInfo();
727 StringRef ClauseName = II->getName();
728 // Parse 'to|link' clauses.
729 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
731 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
737 auto Callback = [this, MT, &SameDirectiveDecls](
738 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
739 Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
742 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
745 // Consume optional ','.
746 if (Tok.is(tok::comma))
749 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
751 return DeclGroupPtrTy();
754 // Skip the last annot_pragma_openmp_end.
757 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
758 return DeclGroupPtrTy();
760 DKind = ParseOpenMPDirectiveKind(*this);
761 while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
762 Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
764 // Here we expect to see some function declaration.
766 assert(TagType == DeclSpec::TST_unspecified);
767 MaybeParseCXX11Attributes(Attrs);
768 ParsingDeclSpec PDS(*this);
769 Ptr = ParseExternalDeclaration(Attrs, &PDS);
772 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
774 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
775 TentativeParsingAction TPA(*this);
776 ConsumeAnnotationToken();
777 DKind = ParseOpenMPDirectiveKind(*this);
778 if (DKind != OMPD_end_declare_target)
785 if (DKind == OMPD_end_declare_target) {
787 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
788 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
789 << getOpenMPDirectiveName(OMPD_end_declare_target);
790 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
792 // Skip the last annot_pragma_openmp_end.
795 Diag(Tok, diag::err_expected_end_declare_target);
796 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
798 Actions.ActOnFinishOpenMPDeclareTargetDirective();
799 return DeclGroupPtrTy();
802 Diag(Tok, diag::err_omp_unknown_directive);
820 case OMPD_parallel_for:
821 case OMPD_parallel_for_simd:
822 case OMPD_parallel_sections:
826 case OMPD_cancellation_point:
828 case OMPD_target_data:
829 case OMPD_target_enter_data:
830 case OMPD_target_exit_data:
831 case OMPD_target_parallel:
832 case OMPD_target_parallel_for:
834 case OMPD_taskloop_simd:
835 case OMPD_distribute:
836 case OMPD_end_declare_target:
837 case OMPD_target_update:
838 case OMPD_distribute_parallel_for:
839 case OMPD_distribute_parallel_for_simd:
840 case OMPD_distribute_simd:
841 case OMPD_target_parallel_for_simd:
842 case OMPD_target_simd:
843 case OMPD_teams_distribute:
844 case OMPD_teams_distribute_simd:
845 case OMPD_teams_distribute_parallel_for_simd:
846 case OMPD_teams_distribute_parallel_for:
847 case OMPD_target_teams:
848 case OMPD_target_teams_distribute:
849 case OMPD_target_teams_distribute_parallel_for:
850 case OMPD_target_teams_distribute_parallel_for_simd:
851 case OMPD_target_teams_distribute_simd:
852 Diag(Tok, diag::err_omp_unexpected_directive)
853 << getOpenMPDirectiveName(DKind);
856 while (Tok.isNot(tok::annot_pragma_openmp_end))
862 /// \brief Parsing of declarative or executable OpenMP directives.
864 /// threadprivate-directive:
865 /// annot_pragma_openmp 'threadprivate' simple-variable-list
866 /// annot_pragma_openmp_end
868 /// declare-reduction-directive:
869 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
870 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
871 /// ('omp_priv' '=' <expression>|<function_call>) ')']
872 /// annot_pragma_openmp_end
874 /// executable-directive:
875 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
876 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
877 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
878 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
879 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
880 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
881 /// 'distribute' | 'target enter data' | 'target exit data' |
882 /// 'target parallel' | 'target parallel for' |
883 /// 'target update' | 'distribute parallel for' |
884 /// 'distribute paralle for simd' | 'distribute simd' |
885 /// 'target parallel for simd' | 'target simd' |
886 /// 'teams distribute' | 'teams distribute simd' |
887 /// 'teams distribute parallel for simd' |
888 /// 'teams distribute parallel for' | 'target teams' |
889 /// 'target teams distribute' |
890 /// 'target teams distribute parallel for' |
891 /// 'target teams distribute parallel for simd' |
892 /// 'target teams distribute simd' {clause}
893 /// annot_pragma_openmp_end
895 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
896 AllowedConstructsKind Allowed) {
897 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
898 ParenBraceBracketBalancer BalancerRAIIObj(*this);
899 SmallVector<OMPClause *, 5> Clauses;
900 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
901 FirstClauses(OMPC_unknown + 1);
902 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
903 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
904 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
905 auto DKind = ParseOpenMPDirectiveKind(*this);
906 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
907 // Name of critical directive.
908 DeclarationNameInfo DirName;
909 StmtResult Directive = StmtError();
910 bool HasAssociatedStatement = true;
911 bool FlushHasClause = false;
914 case OMPD_threadprivate: {
915 if (Allowed != ACK_Any) {
916 Diag(Tok, diag::err_omp_immediate_directive)
917 << getOpenMPDirectiveName(DKind) << 0;
920 ThreadprivateListParserHelper Helper(this);
921 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
922 // The last seen token is annot_pragma_openmp_end - need to check for
924 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
925 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
926 << getOpenMPDirectiveName(OMPD_threadprivate);
927 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
929 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
930 Loc, Helper.getIdentifiers());
931 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
933 SkipUntil(tok::annot_pragma_openmp_end);
936 case OMPD_declare_reduction:
938 if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
939 // The last seen token is annot_pragma_openmp_end - need to check for
941 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
942 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
943 << getOpenMPDirectiveName(OMPD_declare_reduction);
944 while (Tok.isNot(tok::annot_pragma_openmp_end))
948 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
950 SkipUntil(tok::annot_pragma_openmp_end);
953 if (PP.LookAhead(0).is(tok::l_paren)) {
954 FlushHasClause = true;
955 // Push copy of the current token back to stream to properly parse
956 // pseudo-clause OMPFlushClause.
963 case OMPD_cancellation_point:
965 case OMPD_target_enter_data:
966 case OMPD_target_exit_data:
967 case OMPD_target_update:
968 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
969 Diag(Tok, diag::err_omp_immediate_directive)
970 << getOpenMPDirectiveName(DKind) << 0;
972 HasAssociatedStatement = false;
973 // Fall through for further analysis.
984 case OMPD_parallel_for:
985 case OMPD_parallel_for_simd:
986 case OMPD_parallel_sections:
993 case OMPD_target_data:
994 case OMPD_target_parallel:
995 case OMPD_target_parallel_for:
997 case OMPD_taskloop_simd:
998 case OMPD_distribute:
999 case OMPD_distribute_parallel_for:
1000 case OMPD_distribute_parallel_for_simd:
1001 case OMPD_distribute_simd:
1002 case OMPD_target_parallel_for_simd:
1003 case OMPD_target_simd:
1004 case OMPD_teams_distribute:
1005 case OMPD_teams_distribute_simd:
1006 case OMPD_teams_distribute_parallel_for_simd:
1007 case OMPD_teams_distribute_parallel_for:
1008 case OMPD_target_teams:
1009 case OMPD_target_teams_distribute:
1010 case OMPD_target_teams_distribute_parallel_for:
1011 case OMPD_target_teams_distribute_parallel_for_simd:
1012 case OMPD_target_teams_distribute_simd: {
1014 // Parse directive name of the 'critical' directive if any.
1015 if (DKind == OMPD_critical) {
1016 BalancedDelimiterTracker T(*this, tok::l_paren,
1017 tok::annot_pragma_openmp_end);
1018 if (!T.consumeOpen()) {
1019 if (Tok.isAnyIdentifier()) {
1021 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1024 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1028 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1029 CancelRegion = ParseOpenMPDirectiveKind(*this);
1030 if (Tok.isNot(tok::annot_pragma_openmp_end))
1034 if (isOpenMPLoopDirective(DKind))
1035 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1036 if (isOpenMPSimdDirective(DKind))
1037 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1038 ParseScope OMPDirectiveScope(this, ScopeFlags);
1039 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1041 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1042 OpenMPClauseKind CKind =
1045 : FlushHasClause ? OMPC_flush
1046 : getOpenMPClauseKind(PP.getSpelling(Tok));
1047 Actions.StartOpenMPClause(CKind);
1048 FlushHasClause = false;
1050 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1051 FirstClauses[CKind].setInt(true);
1053 FirstClauses[CKind].setPointer(Clause);
1054 Clauses.push_back(Clause);
1058 if (Tok.is(tok::comma))
1060 Actions.EndOpenMPClause();
1062 // End location of the directive.
1063 EndLoc = Tok.getLocation();
1064 // Consume final annot_pragma_openmp_end.
1065 ConsumeAnnotationToken();
1067 // OpenMP [2.13.8, ordered Construct, Syntax]
1068 // If the depend clause is specified, the ordered construct is a stand-alone
1070 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1071 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
1072 Diag(Loc, diag::err_omp_immediate_directive)
1073 << getOpenMPDirectiveName(DKind) << 1
1074 << getOpenMPClauseName(OMPC_depend);
1076 HasAssociatedStatement = false;
1079 StmtResult AssociatedStmt;
1080 if (HasAssociatedStatement) {
1081 // The body is a block scope like in Lambdas and Blocks.
1082 Sema::CompoundScopeRAII CompoundScope(Actions);
1083 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1084 Actions.ActOnStartOfCompoundStmt();
1086 AssociatedStmt = ParseStatement();
1087 Actions.ActOnFinishOfCompoundStmt();
1088 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1089 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1090 DKind == OMPD_target_exit_data) {
1091 Sema::CompoundScopeRAII CompoundScope(Actions);
1092 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1093 Actions.ActOnStartOfCompoundStmt();
1095 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, /*isStmtExpr=*/false);
1096 Actions.ActOnFinishOfCompoundStmt();
1097 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1099 Directive = Actions.ActOnOpenMPExecutableDirective(
1100 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1104 Actions.EndOpenMPDSABlock(Directive.get());
1105 OMPDirectiveScope.Exit();
1108 case OMPD_declare_simd:
1109 case OMPD_declare_target:
1110 case OMPD_end_declare_target:
1111 Diag(Tok, diag::err_omp_unexpected_directive)
1112 << getOpenMPDirectiveName(DKind);
1113 SkipUntil(tok::annot_pragma_openmp_end);
1116 Diag(Tok, diag::err_omp_unknown_directive);
1117 SkipUntil(tok::annot_pragma_openmp_end);
1123 // Parses simple list:
1124 // simple-variable-list:
1125 // '(' id-expression {, id-expression} ')'
1127 bool Parser::ParseOpenMPSimpleVarList(
1128 OpenMPDirectiveKind Kind,
1129 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1131 bool AllowScopeSpecifier) {
1133 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1134 if (T.expectAndConsume(diag::err_expected_lparen_after,
1135 getOpenMPDirectiveName(Kind)))
1137 bool IsCorrect = true;
1138 bool NoIdentIsFound = true;
1140 // Read tokens while ')' or annot_pragma_openmp_end is not found.
1141 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1143 SourceLocation TemplateKWLoc;
1146 Token PrevTok = Tok;
1147 NoIdentIsFound = false;
1149 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1150 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1152 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1154 } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1155 TemplateKWLoc, Name)) {
1157 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1159 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1160 Tok.isNot(tok::annot_pragma_openmp_end)) {
1162 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1164 Diag(PrevTok.getLocation(), diag::err_expected)
1166 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1168 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1171 if (Tok.is(tok::comma)) {
1176 if (NoIdentIsFound) {
1177 Diag(Tok, diag::err_expected) << tok::identifier;
1182 IsCorrect = !T.consumeClose() && IsCorrect;
1187 /// \brief Parsing of OpenMP clauses.
1190 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1191 /// default-clause | private-clause | firstprivate-clause | shared-clause
1192 /// | linear-clause | aligned-clause | collapse-clause |
1193 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1194 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1195 /// mergeable-clause | flush-clause | read-clause | write-clause |
1196 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1197 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1198 /// thread_limit-clause | priority-clause | grainsize-clause |
1199 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1200 /// from-clause | is_device_ptr-clause | task_reduction-clause |
1201 /// in_reduction-clause
1203 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1204 OpenMPClauseKind CKind, bool FirstClause) {
1205 OMPClause *Clause = nullptr;
1206 bool ErrorFound = false;
1207 // Check if clause is allowed for the given directive.
1208 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1209 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1210 << getOpenMPDirectiveName(DKind);
1216 case OMPC_num_threads:
1222 case OMPC_num_teams:
1223 case OMPC_thread_limit:
1225 case OMPC_grainsize:
1226 case OMPC_num_tasks:
1228 // OpenMP [2.5, Restrictions]
1229 // At most one num_threads clause can appear on the directive.
1230 // OpenMP [2.8.1, simd construct, Restrictions]
1231 // Only one safelen clause can appear on a simd directive.
1232 // Only one simdlen clause can appear on a simd directive.
1233 // Only one collapse clause can appear on a simd directive.
1234 // OpenMP [2.9.1, target data construct, Restrictions]
1235 // At most one device clause can appear on the directive.
1236 // OpenMP [2.11.1, task Construct, Restrictions]
1237 // At most one if clause can appear on the directive.
1238 // At most one final clause can appear on the directive.
1239 // OpenMP [teams Construct, Restrictions]
1240 // At most one num_teams clause can appear on the directive.
1241 // At most one thread_limit clause can appear on the directive.
1242 // OpenMP [2.9.1, task Construct, Restrictions]
1243 // At most one priority clause can appear on the directive.
1244 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1245 // At most one grainsize clause can appear on the directive.
1246 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1247 // At most one num_tasks clause can appear on the directive.
1249 Diag(Tok, diag::err_omp_more_one_clause)
1250 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1254 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1255 Clause = ParseOpenMPClause(CKind);
1257 Clause = ParseOpenMPSingleExprClause(CKind);
1260 case OMPC_proc_bind:
1261 // OpenMP [2.14.3.1, Restrictions]
1262 // Only a single default clause may be specified on a parallel, task or
1264 // OpenMP [2.5, parallel Construct, Restrictions]
1265 // At most one proc_bind clause can appear on the directive.
1267 Diag(Tok, diag::err_omp_more_one_clause)
1268 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1272 Clause = ParseOpenMPSimpleClause(CKind);
1275 case OMPC_dist_schedule:
1276 case OMPC_defaultmap:
1277 // OpenMP [2.7.1, Restrictions, p. 3]
1278 // Only one schedule clause can appear on a loop directive.
1279 // OpenMP [2.10.4, Restrictions, p. 106]
1280 // At most one defaultmap clause can appear on the directive.
1282 Diag(Tok, diag::err_omp_more_one_clause)
1283 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1289 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1293 case OMPC_mergeable:
1302 // OpenMP [2.7.1, Restrictions, p. 9]
1303 // Only one ordered clause can appear on a loop directive.
1304 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1305 // Only one nowait clause can appear on a for directive.
1307 Diag(Tok, diag::err_omp_more_one_clause)
1308 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1312 Clause = ParseOpenMPClause(CKind);
1315 case OMPC_firstprivate:
1316 case OMPC_lastprivate:
1318 case OMPC_reduction:
1319 case OMPC_task_reduction:
1320 case OMPC_in_reduction:
1324 case OMPC_copyprivate:
1330 case OMPC_use_device_ptr:
1331 case OMPC_is_device_ptr:
1332 Clause = ParseOpenMPVarListClause(DKind, CKind);
1335 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1336 << getOpenMPDirectiveName(DKind);
1337 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1339 case OMPC_threadprivate:
1341 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1342 << getOpenMPDirectiveName(DKind);
1343 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1346 return ErrorFound ? nullptr : Clause;
1349 /// Parses simple expression in parens for single-expression clauses of OpenMP
1351 /// \param RLoc Returned location of right paren.
1352 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
1353 SourceLocation &RLoc) {
1354 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1355 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1358 SourceLocation ELoc = Tok.getLocation();
1359 ExprResult LHS(ParseCastExpression(
1360 /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1361 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1362 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1367 RLoc = T.getCloseLocation();
1371 /// \brief Parsing of OpenMP clauses with single expressions like 'final',
1372 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1373 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1376 /// 'final' '(' expression ')'
1378 /// num_threads-clause:
1379 /// 'num_threads' '(' expression ')'
1382 /// 'safelen' '(' expression ')'
1385 /// 'simdlen' '(' expression ')'
1387 /// collapse-clause:
1388 /// 'collapse' '(' expression ')'
1390 /// priority-clause:
1391 /// 'priority' '(' expression ')'
1393 /// grainsize-clause:
1394 /// 'grainsize' '(' expression ')'
1396 /// num_tasks-clause:
1397 /// 'num_tasks' '(' expression ')'
1400 /// 'hint' '(' expression ')'
1402 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
1403 SourceLocation Loc = ConsumeToken();
1404 SourceLocation LLoc = Tok.getLocation();
1405 SourceLocation RLoc;
1407 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1409 if (Val.isInvalid())
1412 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1415 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1418 /// 'default' '(' 'none' | 'shared' ')
1420 /// proc_bind-clause:
1421 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1423 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
1424 SourceLocation Loc = Tok.getLocation();
1425 SourceLocation LOpen = ConsumeToken();
1427 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1428 if (T.expectAndConsume(diag::err_expected_lparen_after,
1429 getOpenMPClauseName(Kind)))
1432 unsigned Type = getOpenMPSimpleClauseType(
1433 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1434 SourceLocation TypeLoc = Tok.getLocation();
1435 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1436 Tok.isNot(tok::annot_pragma_openmp_end))
1442 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1446 /// \brief Parsing of OpenMP clauses like 'ordered'.
1457 /// mergeable-clause:
1472 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
1473 SourceLocation Loc = Tok.getLocation();
1476 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1480 /// \brief Parsing of OpenMP clauses with single expressions and some additional
1481 /// argument like 'schedule' or 'dist_schedule'.
1483 /// schedule-clause:
1484 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1488 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1491 /// 'defaultmap' '(' modifier ':' kind ')'
1493 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
1494 SourceLocation Loc = ConsumeToken();
1495 SourceLocation DelimLoc;
1497 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1498 if (T.expectAndConsume(diag::err_expected_lparen_after,
1499 getOpenMPClauseName(Kind)))
1503 SmallVector<unsigned, 4> Arg;
1504 SmallVector<SourceLocation, 4> KLoc;
1505 if (Kind == OMPC_schedule) {
1506 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1507 Arg.resize(NumberOfElements);
1508 KLoc.resize(NumberOfElements);
1509 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1510 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1511 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1512 auto KindModifier = getOpenMPSimpleClauseType(
1513 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1514 if (KindModifier > OMPC_SCHEDULE_unknown) {
1516 Arg[Modifier1] = KindModifier;
1517 KLoc[Modifier1] = Tok.getLocation();
1518 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1519 Tok.isNot(tok::annot_pragma_openmp_end))
1521 if (Tok.is(tok::comma)) {
1522 // Parse ',' 'modifier'
1524 KindModifier = getOpenMPSimpleClauseType(
1525 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1526 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1528 : (unsigned)OMPC_SCHEDULE_unknown;
1529 KLoc[Modifier2] = Tok.getLocation();
1530 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1531 Tok.isNot(tok::annot_pragma_openmp_end))
1535 if (Tok.is(tok::colon))
1538 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1539 KindModifier = getOpenMPSimpleClauseType(
1540 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1542 Arg[ScheduleKind] = KindModifier;
1543 KLoc[ScheduleKind] = Tok.getLocation();
1544 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1545 Tok.isNot(tok::annot_pragma_openmp_end))
1547 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1548 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1549 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1551 DelimLoc = ConsumeAnyToken();
1552 } else if (Kind == OMPC_dist_schedule) {
1553 Arg.push_back(getOpenMPSimpleClauseType(
1554 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1555 KLoc.push_back(Tok.getLocation());
1556 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1557 Tok.isNot(tok::annot_pragma_openmp_end))
1559 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1560 DelimLoc = ConsumeAnyToken();
1561 } else if (Kind == OMPC_defaultmap) {
1562 // Get a defaultmap modifier
1563 Arg.push_back(getOpenMPSimpleClauseType(
1564 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1565 KLoc.push_back(Tok.getLocation());
1566 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1567 Tok.isNot(tok::annot_pragma_openmp_end))
1570 if (Tok.is(tok::colon))
1572 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1573 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1574 // Get a defaultmap kind
1575 Arg.push_back(getOpenMPSimpleClauseType(
1576 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1577 KLoc.push_back(Tok.getLocation());
1578 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1579 Tok.isNot(tok::annot_pragma_openmp_end))
1582 assert(Kind == OMPC_if);
1583 KLoc.push_back(Tok.getLocation());
1584 TentativeParsingAction TPA(*this);
1585 Arg.push_back(ParseOpenMPDirectiveKind(*this));
1586 if (Arg.back() != OMPD_unknown) {
1588 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1590 DelimLoc = ConsumeToken();
1593 Arg.back() = OMPD_unknown;
1599 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1600 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1602 if (NeedAnExpression) {
1603 SourceLocation ELoc = Tok.getLocation();
1604 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
1605 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
1606 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1612 if (NeedAnExpression && Val.isInvalid())
1615 return Actions.ActOnOpenMPSingleExprWithArgClause(
1616 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1617 T.getCloseLocation());
1620 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
1621 UnqualifiedId &ReductionId) {
1622 SourceLocation TemplateKWLoc;
1623 if (ReductionIdScopeSpec.isEmpty()) {
1625 switch (P.getCurToken().getKind()) {
1653 if (OOK != OO_None) {
1654 SourceLocation OpLoc = P.ConsumeToken();
1655 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
1656 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
1660 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
1661 /*AllowDestructorName*/ false,
1662 /*AllowConstructorName*/ false,
1663 /*AllowDeductionGuide*/ false,
1664 nullptr, TemplateKWLoc, ReductionId);
1667 /// Parses clauses with list.
1668 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
1669 OpenMPClauseKind Kind,
1670 SmallVectorImpl<Expr *> &Vars,
1671 OpenMPVarListDataTy &Data) {
1672 UnqualifiedId UnqualifiedReductionId;
1673 bool InvalidReductionId = false;
1674 bool MapTypeModifierSpecified = false;
1677 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1678 if (T.expectAndConsume(diag::err_expected_lparen_after,
1679 getOpenMPClauseName(Kind)))
1682 bool NeedRParenForLinear = false;
1683 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
1684 tok::annot_pragma_openmp_end);
1685 // Handle reduction-identifier for reduction clause.
1686 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
1687 Kind == OMPC_in_reduction) {
1688 ColonProtectionRAIIObject ColonRAII(*this);
1689 if (getLangOpts().CPlusPlus)
1690 ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
1691 /*ObjectType=*/nullptr,
1692 /*EnteringContext=*/false);
1693 InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
1694 UnqualifiedReductionId);
1695 if (InvalidReductionId) {
1696 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1699 if (Tok.is(tok::colon))
1700 Data.ColonLoc = ConsumeToken();
1702 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
1703 if (!InvalidReductionId)
1705 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1706 } else if (Kind == OMPC_depend) {
1707 // Handle dependency type for depend clause.
1708 ColonProtectionRAIIObject ColonRAII(*this);
1710 static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
1711 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
1712 Data.DepLinMapLoc = Tok.getLocation();
1714 if (Data.DepKind == OMPC_DEPEND_unknown) {
1715 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1719 // Special processing for depend(source) clause.
1720 if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
1726 if (Tok.is(tok::colon))
1727 Data.ColonLoc = ConsumeToken();
1729 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1730 : diag::warn_pragma_expected_colon)
1731 << "dependency type";
1733 } else if (Kind == OMPC_linear) {
1734 // Try to parse modifier if any.
1735 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
1736 Data.LinKind = static_cast<OpenMPLinearClauseKind>(
1737 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
1738 Data.DepLinMapLoc = ConsumeToken();
1739 LinearT.consumeOpen();
1740 NeedRParenForLinear = true;
1742 } else if (Kind == OMPC_map) {
1743 // Handle map type for map clause.
1744 ColonProtectionRAIIObject ColonRAII(*this);
1746 /// The map clause modifier token can be either a identifier or the C++
1748 auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
1749 return Tok.isOneOf(tok::identifier, tok::kw_delete);
1752 // The first identifier may be a list item, a map-type or a
1753 // map-type-modifier. The map modifier can also be delete which has the same
1754 // spelling of the C++ delete keyword.
1756 IsMapClauseModifierToken(Tok)
1757 ? static_cast<OpenMPMapClauseKind>(
1758 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1760 Data.DepLinMapLoc = Tok.getLocation();
1761 bool ColonExpected = false;
1763 if (IsMapClauseModifierToken(Tok)) {
1764 if (PP.LookAhead(0).is(tok::colon)) {
1765 if (Data.MapType == OMPC_MAP_unknown)
1766 Diag(Tok, diag::err_omp_unknown_map_type);
1767 else if (Data.MapType == OMPC_MAP_always)
1768 Diag(Tok, diag::err_omp_map_type_missing);
1770 } else if (PP.LookAhead(0).is(tok::comma)) {
1771 if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
1772 PP.LookAhead(2).is(tok::colon)) {
1773 Data.MapTypeModifier = Data.MapType;
1774 if (Data.MapTypeModifier != OMPC_MAP_always) {
1775 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1776 Data.MapTypeModifier = OMPC_MAP_unknown;
1778 MapTypeModifierSpecified = true;
1784 IsMapClauseModifierToken(Tok)
1785 ? static_cast<OpenMPMapClauseKind>(
1786 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1788 if (Data.MapType == OMPC_MAP_unknown ||
1789 Data.MapType == OMPC_MAP_always)
1790 Diag(Tok, diag::err_omp_unknown_map_type);
1793 Data.MapType = OMPC_MAP_tofrom;
1794 Data.IsMapTypeImplicit = true;
1796 } else if (IsMapClauseModifierToken(PP.LookAhead(0))) {
1797 if (PP.LookAhead(1).is(tok::colon)) {
1798 Data.MapTypeModifier = Data.MapType;
1799 if (Data.MapTypeModifier != OMPC_MAP_always) {
1800 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1801 Data.MapTypeModifier = OMPC_MAP_unknown;
1803 MapTypeModifierSpecified = true;
1808 IsMapClauseModifierToken(Tok)
1809 ? static_cast<OpenMPMapClauseKind>(
1810 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1812 if (Data.MapType == OMPC_MAP_unknown ||
1813 Data.MapType == OMPC_MAP_always)
1814 Diag(Tok, diag::err_omp_unknown_map_type);
1817 Data.MapType = OMPC_MAP_tofrom;
1818 Data.IsMapTypeImplicit = true;
1821 Data.MapType = OMPC_MAP_tofrom;
1822 Data.IsMapTypeImplicit = true;
1825 Data.MapType = OMPC_MAP_tofrom;
1826 Data.IsMapTypeImplicit = true;
1829 if (Tok.is(tok::colon))
1830 Data.ColonLoc = ConsumeToken();
1831 else if (ColonExpected)
1832 Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
1836 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
1837 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
1838 (Kind == OMPC_reduction && !InvalidReductionId) ||
1839 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
1840 (!MapTypeModifierSpecified ||
1841 Data.MapTypeModifier == OMPC_MAP_always)) ||
1842 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
1843 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1844 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
1845 Tok.isNot(tok::annot_pragma_openmp_end))) {
1846 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
1848 ExprResult VarExpr =
1849 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
1850 if (VarExpr.isUsable())
1851 Vars.push_back(VarExpr.get());
1853 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1857 IsComma = Tok.is(tok::comma);
1860 else if (Tok.isNot(tok::r_paren) &&
1861 Tok.isNot(tok::annot_pragma_openmp_end) &&
1862 (!MayHaveTail || Tok.isNot(tok::colon)))
1863 Diag(Tok, diag::err_omp_expected_punc)
1864 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
1865 : getOpenMPClauseName(Kind))
1866 << (Kind == OMPC_flush);
1869 // Parse ')' for linear clause with modifier.
1870 if (NeedRParenForLinear)
1871 LinearT.consumeClose();
1873 // Parse ':' linear-step (or ':' alignment).
1874 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
1876 Data.ColonLoc = Tok.getLocation();
1877 SourceLocation ELoc = ConsumeToken();
1878 ExprResult Tail = ParseAssignmentExpression();
1879 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
1880 if (Tail.isUsable())
1881 Data.TailExpr = Tail.get();
1883 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1889 if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
1891 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1892 (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
1897 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
1898 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
1902 /// 'private' '(' list ')'
1903 /// firstprivate-clause:
1904 /// 'firstprivate' '(' list ')'
1905 /// lastprivate-clause:
1906 /// 'lastprivate' '(' list ')'
1908 /// 'shared' '(' list ')'
1910 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
1912 /// 'aligned' '(' list [ ':' alignment ] ')'
1913 /// reduction-clause:
1914 /// 'reduction' '(' reduction-identifier ':' list ')'
1915 /// task_reduction-clause:
1916 /// 'task_reduction' '(' reduction-identifier ':' list ')'
1917 /// in_reduction-clause:
1918 /// 'in_reduction' '(' reduction-identifier ':' list ')'
1919 /// copyprivate-clause:
1920 /// 'copyprivate' '(' list ')'
1922 /// 'flush' '(' list ')'
1924 /// 'depend' '(' in | out | inout : list | source ')'
1926 /// 'map' '(' [ [ always , ]
1927 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
1929 /// 'to' '(' list ')'
1931 /// 'from' '(' list ')'
1932 /// use_device_ptr-clause:
1933 /// 'use_device_ptr' '(' list ')'
1934 /// is_device_ptr-clause:
1935 /// 'is_device_ptr' '(' list ')'
1937 /// For 'linear' clause linear-list may have the following forms:
1940 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
1941 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
1942 OpenMPClauseKind Kind) {
1943 SourceLocation Loc = Tok.getLocation();
1944 SourceLocation LOpen = ConsumeToken();
1945 SmallVector<Expr *, 4> Vars;
1946 OpenMPVarListDataTy Data;
1948 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
1951 return Actions.ActOnOpenMPVarListClause(
1952 Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
1953 Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1954 Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,