1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
12 //===----------------------------------------------------------------------===//
14 #include "RAIIObjectsForParser.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/StmtOpenMP.h"
17 #include "clang/Parse/ParseDiagnostic.h"
18 #include "clang/Parse/Parser.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_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
123 { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
125 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
126 auto Tok = P.getCurToken();
129 ? static_cast<unsigned>(OMPD_unknown)
130 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
131 if (DKind == OMPD_unknown)
134 for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
135 if (DKind != F[i][0])
138 Tok = P.getPreprocessor().LookAhead(0);
141 ? static_cast<unsigned>(OMPD_unknown)
142 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
143 if (SDKind == OMPD_unknown)
146 if (SDKind == F[i][1]) {
151 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
155 static DeclarationName parseOpenMPReductionId(Parser &P) {
156 Token Tok = P.getCurToken();
157 Sema &Actions = P.getActions();
158 OverloadedOperatorKind OOK = OO_None;
159 // Allow to use 'operator' keyword for C++ operators
160 bool WithOperator = false;
161 if (Tok.is(tok::kw_operator)) {
163 Tok = P.getCurToken();
166 switch (Tok.getKind()) {
167 case tok::plus: // '+'
170 case tok::minus: // '-'
173 case tok::star: // '*'
176 case tok::amp: // '&'
179 case tok::pipe: // '|'
182 case tok::caret: // '^'
185 case tok::ampamp: // '&&'
188 case tok::pipepipe: // '||'
191 case tok::identifier: // identifier
195 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
196 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
197 Parser::StopBeforeMatch);
198 return DeclarationName();
201 auto &DeclNames = Actions.getASTContext().DeclarationNames;
202 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
203 : DeclNames.getCXXOperatorName(OOK);
206 /// \brief Parse 'omp declare reduction' construct.
208 /// declare-reduction-directive:
209 /// annot_pragma_openmp 'declare' 'reduction'
210 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
211 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
212 /// annot_pragma_openmp_end
213 /// <reduction_id> is either a base language identifier or one of the following
214 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
216 Parser::DeclGroupPtrTy
217 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
219 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
220 if (T.expectAndConsume(diag::err_expected_lparen_after,
221 getOpenMPDirectiveName(OMPD_declare_reduction))) {
222 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
223 return DeclGroupPtrTy();
226 DeclarationName Name = parseOpenMPReductionId(*this);
227 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
228 return DeclGroupPtrTy();
231 bool IsCorrect = !ExpectAndConsume(tok::colon);
233 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
234 return DeclGroupPtrTy();
236 IsCorrect = IsCorrect && !Name.isEmpty();
238 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
239 Diag(Tok.getLocation(), diag::err_expected_type);
243 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
244 return DeclGroupPtrTy();
246 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
247 // Parse list of types until ':' token.
249 ColonProtectionRAIIObject ColonRAII(*this);
251 TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS);
254 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
255 if (!ReductionType.isNull()) {
256 ReductionTypes.push_back(
257 std::make_pair(ReductionType, Range.getBegin()));
260 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
264 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
268 if (ExpectAndConsume(tok::comma)) {
270 if (Tok.is(tok::annot_pragma_openmp_end)) {
271 Diag(Tok.getLocation(), diag::err_expected_type);
272 return DeclGroupPtrTy();
275 } while (Tok.isNot(tok::annot_pragma_openmp_end));
277 if (ReductionTypes.empty()) {
278 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
279 return DeclGroupPtrTy();
282 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
283 return DeclGroupPtrTy();
286 if (ExpectAndConsume(tok::colon))
289 if (Tok.is(tok::annot_pragma_openmp_end)) {
290 Diag(Tok.getLocation(), diag::err_expected_expression);
291 return DeclGroupPtrTy();
294 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
295 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
297 // Parse <combiner> expression and then parse initializer if any for each
299 unsigned I = 0, E = ReductionTypes.size();
300 for (auto *D : DRD.get()) {
301 TentativeParsingAction TPA(*this);
302 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
303 Scope::OpenMPDirectiveScope);
304 // Parse <combiner> expression.
305 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
306 ExprResult CombinerResult =
307 Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
308 D->getLocation(), /*DiscardedValue=*/true);
309 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
311 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
312 Tok.isNot(tok::annot_pragma_openmp_end)) {
317 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
318 ExprResult InitializerResult;
319 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
320 // Parse <initializer> expression.
321 if (Tok.is(tok::identifier) &&
322 Tok.getIdentifierInfo()->isStr("initializer"))
325 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
331 BalancedDelimiterTracker T(*this, tok::l_paren,
332 tok::annot_pragma_openmp_end);
334 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
336 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
337 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
338 Scope::OpenMPDirectiveScope);
340 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
341 InitializerResult = Actions.ActOnFinishFullExpr(
342 ParseAssignmentExpression().get(), D->getLocation(),
343 /*DiscardedValue=*/true);
344 Actions.ActOnOpenMPDeclareReductionInitializerEnd(
345 D, InitializerResult.get());
346 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
347 Tok.isNot(tok::annot_pragma_openmp_end)) {
353 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
358 // Revert parsing if not the last type, otherwise accept it, we're done with
365 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
370 /// RAII that recreates function context for correct parsing of clauses of
371 /// 'declare simd' construct.
372 /// OpenMP, 2.8.2 declare simd Construct
373 /// The expressions appearing in the clauses of this directive are evaluated in
374 /// the scope of the arguments of the function declaration or definition.
375 class FNContextRAII final {
377 Sema::CXXThisScopeRAII *ThisScope;
378 Parser::ParseScope *TempScope;
379 Parser::ParseScope *FnScope;
380 bool HasTemplateScope = false;
381 bool HasFunScope = false;
382 FNContextRAII() = delete;
383 FNContextRAII(const FNContextRAII &) = delete;
384 FNContextRAII &operator=(const FNContextRAII &) = delete;
387 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
388 Decl *D = *Ptr.get().begin();
389 NamedDecl *ND = dyn_cast<NamedDecl>(D);
390 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
391 Sema &Actions = P.getActions();
393 // Allow 'this' within late-parsed attributes.
394 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
395 ND && ND->isCXXInstanceMember());
397 // If the Decl is templatized, add template parameters to scope.
398 HasTemplateScope = D->isTemplateDecl();
400 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
401 if (HasTemplateScope)
402 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
404 // If the Decl is on a function, add function parameters to the scope.
405 HasFunScope = D->isFunctionOrFunctionTemplate();
406 FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
409 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
413 P.getActions().ActOnExitFunctionContext();
414 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
416 if (HasTemplateScope)
425 /// Parses clauses for 'declare simd' directive.
427 /// 'inbranch' | 'notinbranch'
428 /// 'simdlen' '(' <expr> ')'
429 /// { 'uniform' '(' <argument_list> ')' }
430 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
431 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
432 static bool parseDeclareSimdClauses(
433 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
434 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
435 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
436 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
438 const Token &Tok = P.getCurToken();
439 bool IsError = false;
440 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
441 if (Tok.isNot(tok::identifier))
443 OMPDeclareSimdDeclAttr::BranchStateTy Out;
444 IdentifierInfo *II = Tok.getIdentifierInfo();
445 StringRef ClauseName = II->getName();
446 // Parse 'inranch|notinbranch' clauses.
447 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
448 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
449 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
451 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
455 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
457 } else if (ClauseName.equals("simdlen")) {
458 if (SimdLen.isUsable()) {
459 P.Diag(Tok, diag::err_omp_more_one_clause)
460 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
465 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
466 if (SimdLen.isInvalid())
469 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
470 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
471 CKind == OMPC_linear) {
472 Parser::OpenMPVarListDataTy Data;
473 auto *Vars = &Uniforms;
474 if (CKind == OMPC_aligned)
476 else if (CKind == OMPC_linear)
480 if (P.ParseOpenMPVarList(OMPD_declare_simd,
481 getOpenMPClauseKind(ClauseName), *Vars, Data))
483 if (CKind == OMPC_aligned)
484 Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
485 else if (CKind == OMPC_linear) {
486 if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
488 Data.LinKind = OMPC_LINEAR_val;
489 LinModifiers.append(Linears.size() - LinModifiers.size(),
491 Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
494 // TODO: add parsing of other clauses.
498 if (Tok.is(tok::comma))
504 /// Parse clauses for '#pragma omp declare simd'.
505 Parser::DeclGroupPtrTy
506 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
507 CachedTokens &Toks, SourceLocation Loc) {
509 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
510 // Consume the previously pushed token.
511 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
513 FNContextRAII FnContext(*this, Ptr);
514 OMPDeclareSimdDeclAttr::BranchStateTy BS =
515 OMPDeclareSimdDeclAttr::BS_Undefined;
517 SmallVector<Expr *, 4> Uniforms;
518 SmallVector<Expr *, 4> Aligneds;
519 SmallVector<Expr *, 4> Alignments;
520 SmallVector<Expr *, 4> Linears;
521 SmallVector<unsigned, 4> LinModifiers;
522 SmallVector<Expr *, 4> Steps;
524 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
525 Alignments, Linears, LinModifiers, Steps);
526 // Need to check for extra tokens.
527 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
528 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
529 << getOpenMPDirectiveName(OMPD_declare_simd);
530 while (Tok.isNot(tok::annot_pragma_openmp_end))
533 // Skip the last annot_pragma_openmp_end.
534 SourceLocation EndLoc = ConsumeToken();
536 return Actions.ActOnOpenMPDeclareSimdDirective(
537 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
538 LinModifiers, Steps, SourceRange(Loc, EndLoc));
543 /// \brief Parsing of declarative OpenMP directives.
545 /// threadprivate-directive:
546 /// annot_pragma_openmp 'threadprivate' simple-variable-list
547 /// annot_pragma_openmp_end
549 /// declare-reduction-directive:
550 /// annot_pragma_openmp 'declare' 'reduction' [...]
551 /// annot_pragma_openmp_end
553 /// declare-simd-directive:
554 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
555 /// annot_pragma_openmp_end
556 /// <function declaration/definition>
558 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
559 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
560 DeclSpec::TST TagType, Decl *Tag) {
561 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
562 ParenBraceBracketBalancer BalancerRAIIObj(*this);
564 SourceLocation Loc = ConsumeToken();
565 auto DKind = ParseOpenMPDirectiveKind(*this);
568 case OMPD_threadprivate: {
570 ThreadprivateListParserHelper Helper(this);
571 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
572 // The last seen token is annot_pragma_openmp_end - need to check for
574 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
575 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
576 << getOpenMPDirectiveName(OMPD_threadprivate);
577 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
579 // Skip the last annot_pragma_openmp_end.
581 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
582 Helper.getIdentifiers());
586 case OMPD_declare_reduction:
588 if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
589 // The last seen token is annot_pragma_openmp_end - need to check for
591 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
592 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
593 << getOpenMPDirectiveName(OMPD_declare_reduction);
594 while (Tok.isNot(tok::annot_pragma_openmp_end))
597 // Skip the last annot_pragma_openmp_end.
602 case OMPD_declare_simd: {
604 // { #pragma omp declare simd }
605 // <function-declaration-or-definition>
609 while(Tok.isNot(tok::annot_pragma_openmp_end)) {
617 if (Tok.is(tok::annot_pragma_openmp))
618 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
619 else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
620 // Here we expect to see some function declaration.
622 assert(TagType == DeclSpec::TST_unspecified);
623 MaybeParseCXX11Attributes(Attrs);
624 ParsingDeclSpec PDS(*this);
625 Ptr = ParseExternalDeclaration(Attrs, &PDS);
628 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
632 Diag(Loc, diag::err_omp_decl_in_declare_simd);
633 return DeclGroupPtrTy();
635 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
637 case OMPD_declare_target: {
638 SourceLocation DTLoc = ConsumeAnyToken();
639 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
640 // OpenMP 4.5 syntax with list of entities.
641 llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
642 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
643 OMPDeclareTargetDeclAttr::MapTypeTy MT =
644 OMPDeclareTargetDeclAttr::MT_To;
645 if (Tok.is(tok::identifier)) {
646 IdentifierInfo *II = Tok.getIdentifierInfo();
647 StringRef ClauseName = II->getName();
648 // Parse 'to|link' clauses.
649 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
651 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
657 auto Callback = [this, MT, &SameDirectiveDecls](
658 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
659 Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
662 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
665 // Consume optional ','.
666 if (Tok.is(tok::comma))
669 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
671 return DeclGroupPtrTy();
674 // Skip the last annot_pragma_openmp_end.
677 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
678 return DeclGroupPtrTy();
680 DKind = ParseOpenMPDirectiveKind(*this);
681 while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
682 Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
683 ParsedAttributesWithRange attrs(AttrFactory);
684 MaybeParseCXX11Attributes(attrs);
685 ParseExternalDeclaration(attrs);
686 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
687 TentativeParsingAction TPA(*this);
689 DKind = ParseOpenMPDirectiveKind(*this);
690 if (DKind != OMPD_end_declare_target)
697 if (DKind == OMPD_end_declare_target) {
699 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
700 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
701 << getOpenMPDirectiveName(OMPD_end_declare_target);
702 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
704 // Skip the last annot_pragma_openmp_end.
707 Diag(Tok, diag::err_expected_end_declare_target);
708 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
710 Actions.ActOnFinishOpenMPDeclareTargetDirective();
711 return DeclGroupPtrTy();
714 Diag(Tok, diag::err_omp_unknown_directive);
732 case OMPD_parallel_for:
733 case OMPD_parallel_for_simd:
734 case OMPD_parallel_sections:
738 case OMPD_cancellation_point:
740 case OMPD_target_data:
741 case OMPD_target_enter_data:
742 case OMPD_target_exit_data:
743 case OMPD_target_parallel:
744 case OMPD_target_parallel_for:
746 case OMPD_taskloop_simd:
747 case OMPD_distribute:
748 case OMPD_end_declare_target:
749 case OMPD_target_update:
750 case OMPD_distribute_parallel_for:
751 case OMPD_distribute_parallel_for_simd:
752 case OMPD_distribute_simd:
753 case OMPD_target_parallel_for_simd:
754 case OMPD_target_simd:
755 case OMPD_teams_distribute:
756 case OMPD_teams_distribute_simd:
757 case OMPD_teams_distribute_parallel_for_simd:
758 case OMPD_teams_distribute_parallel_for:
759 case OMPD_target_teams:
760 case OMPD_target_teams_distribute:
761 case OMPD_target_teams_distribute_parallel_for:
762 case OMPD_target_teams_distribute_parallel_for_simd:
763 Diag(Tok, diag::err_omp_unexpected_directive)
764 << getOpenMPDirectiveName(DKind);
767 while (Tok.isNot(tok::annot_pragma_openmp_end))
773 /// \brief Parsing of declarative or executable OpenMP directives.
775 /// threadprivate-directive:
776 /// annot_pragma_openmp 'threadprivate' simple-variable-list
777 /// annot_pragma_openmp_end
779 /// declare-reduction-directive:
780 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
781 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
782 /// ('omp_priv' '=' <expression>|<function_call>) ')']
783 /// annot_pragma_openmp_end
785 /// executable-directive:
786 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
787 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
788 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
789 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
790 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
791 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
792 /// 'distribute' | 'target enter data' | 'target exit data' |
793 /// 'target parallel' | 'target parallel for' |
794 /// 'target update' | 'distribute parallel for' |
795 /// 'distribute paralle for simd' | 'distribute simd' |
796 /// 'target parallel for simd' | 'target simd' |
797 /// 'teams distribute' | 'teams distribute simd' |
798 /// 'teams distribute parallel for simd' |
799 /// 'teams distribute parallel for' | 'target teams' |
800 /// 'target teams distribute' |
801 /// 'target teams distribute parallel for' |
802 /// 'target teams distribute parallel for simd' {clause}
803 /// annot_pragma_openmp_end
805 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
806 AllowedContsructsKind Allowed) {
807 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
808 ParenBraceBracketBalancer BalancerRAIIObj(*this);
809 SmallVector<OMPClause *, 5> Clauses;
810 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
811 FirstClauses(OMPC_unknown + 1);
812 unsigned ScopeFlags =
813 Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
814 SourceLocation Loc = ConsumeToken(), EndLoc;
815 auto DKind = ParseOpenMPDirectiveKind(*this);
816 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
817 // Name of critical directive.
818 DeclarationNameInfo DirName;
819 StmtResult Directive = StmtError();
820 bool HasAssociatedStatement = true;
821 bool FlushHasClause = false;
824 case OMPD_threadprivate: {
825 if (Allowed != ACK_Any) {
826 Diag(Tok, diag::err_omp_immediate_directive)
827 << getOpenMPDirectiveName(DKind) << 0;
830 ThreadprivateListParserHelper Helper(this);
831 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
832 // The last seen token is annot_pragma_openmp_end - need to check for
834 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
835 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
836 << getOpenMPDirectiveName(OMPD_threadprivate);
837 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
839 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
840 Loc, Helper.getIdentifiers());
841 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
843 SkipUntil(tok::annot_pragma_openmp_end);
846 case OMPD_declare_reduction:
848 if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
849 // The last seen token is annot_pragma_openmp_end - need to check for
851 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
852 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
853 << getOpenMPDirectiveName(OMPD_declare_reduction);
854 while (Tok.isNot(tok::annot_pragma_openmp_end))
858 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
860 SkipUntil(tok::annot_pragma_openmp_end);
863 if (PP.LookAhead(0).is(tok::l_paren)) {
864 FlushHasClause = true;
865 // Push copy of the current token back to stream to properly parse
866 // pseudo-clause OMPFlushClause.
872 case OMPD_cancellation_point:
874 case OMPD_target_enter_data:
875 case OMPD_target_exit_data:
876 case OMPD_target_update:
877 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
878 Diag(Tok, diag::err_omp_immediate_directive)
879 << getOpenMPDirectiveName(DKind) << 0;
881 HasAssociatedStatement = false;
882 // Fall through for further analysis.
892 case OMPD_parallel_for:
893 case OMPD_parallel_for_simd:
894 case OMPD_parallel_sections:
901 case OMPD_target_data:
902 case OMPD_target_parallel:
903 case OMPD_target_parallel_for:
905 case OMPD_taskloop_simd:
906 case OMPD_distribute:
907 case OMPD_distribute_parallel_for:
908 case OMPD_distribute_parallel_for_simd:
909 case OMPD_distribute_simd:
910 case OMPD_target_parallel_for_simd:
911 case OMPD_target_simd:
912 case OMPD_teams_distribute:
913 case OMPD_teams_distribute_simd:
914 case OMPD_teams_distribute_parallel_for_simd:
915 case OMPD_teams_distribute_parallel_for:
916 case OMPD_target_teams:
917 case OMPD_target_teams_distribute:
918 case OMPD_target_teams_distribute_parallel_for:
919 case OMPD_target_teams_distribute_parallel_for_simd: {
921 // Parse directive name of the 'critical' directive if any.
922 if (DKind == OMPD_critical) {
923 BalancedDelimiterTracker T(*this, tok::l_paren,
924 tok::annot_pragma_openmp_end);
925 if (!T.consumeOpen()) {
926 if (Tok.isAnyIdentifier()) {
928 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
931 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
935 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
936 CancelRegion = ParseOpenMPDirectiveKind(*this);
937 if (Tok.isNot(tok::annot_pragma_openmp_end))
941 if (isOpenMPLoopDirective(DKind))
942 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
943 if (isOpenMPSimdDirective(DKind))
944 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
945 ParseScope OMPDirectiveScope(this, ScopeFlags);
946 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
948 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
949 OpenMPClauseKind CKind =
952 : FlushHasClause ? OMPC_flush
953 : getOpenMPClauseKind(PP.getSpelling(Tok));
954 Actions.StartOpenMPClause(CKind);
955 FlushHasClause = false;
957 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
958 FirstClauses[CKind].setInt(true);
960 FirstClauses[CKind].setPointer(Clause);
961 Clauses.push_back(Clause);
965 if (Tok.is(tok::comma))
967 Actions.EndOpenMPClause();
969 // End location of the directive.
970 EndLoc = Tok.getLocation();
971 // Consume final annot_pragma_openmp_end.
974 // OpenMP [2.13.8, ordered Construct, Syntax]
975 // If the depend clause is specified, the ordered construct is a stand-alone
977 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
978 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
979 Diag(Loc, diag::err_omp_immediate_directive)
980 << getOpenMPDirectiveName(DKind) << 1
981 << getOpenMPClauseName(OMPC_depend);
983 HasAssociatedStatement = false;
986 StmtResult AssociatedStmt;
987 if (HasAssociatedStatement) {
988 // The body is a block scope like in Lambdas and Blocks.
989 Sema::CompoundScopeRAII CompoundScope(Actions);
990 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
991 Actions.ActOnStartOfCompoundStmt();
993 AssociatedStmt = ParseStatement();
994 Actions.ActOnFinishOfCompoundStmt();
995 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
997 Directive = Actions.ActOnOpenMPExecutableDirective(
998 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1002 Actions.EndOpenMPDSABlock(Directive.get());
1003 OMPDirectiveScope.Exit();
1006 case OMPD_declare_simd:
1007 case OMPD_declare_target:
1008 case OMPD_end_declare_target:
1009 Diag(Tok, diag::err_omp_unexpected_directive)
1010 << getOpenMPDirectiveName(DKind);
1011 SkipUntil(tok::annot_pragma_openmp_end);
1014 Diag(Tok, diag::err_omp_unknown_directive);
1015 SkipUntil(tok::annot_pragma_openmp_end);
1021 // Parses simple list:
1022 // simple-variable-list:
1023 // '(' id-expression {, id-expression} ')'
1025 bool Parser::ParseOpenMPSimpleVarList(
1026 OpenMPDirectiveKind Kind,
1027 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1029 bool AllowScopeSpecifier) {
1031 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1032 if (T.expectAndConsume(diag::err_expected_lparen_after,
1033 getOpenMPDirectiveName(Kind)))
1035 bool IsCorrect = true;
1036 bool NoIdentIsFound = true;
1038 // Read tokens while ')' or annot_pragma_openmp_end is not found.
1039 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1041 SourceLocation TemplateKWLoc;
1044 Token PrevTok = Tok;
1045 NoIdentIsFound = false;
1047 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1048 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1050 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1052 } else if (ParseUnqualifiedId(SS, false, false, false, nullptr,
1053 TemplateKWLoc, Name)) {
1055 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1057 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1058 Tok.isNot(tok::annot_pragma_openmp_end)) {
1060 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1062 Diag(PrevTok.getLocation(), diag::err_expected)
1064 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1066 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1069 if (Tok.is(tok::comma)) {
1074 if (NoIdentIsFound) {
1075 Diag(Tok, diag::err_expected) << tok::identifier;
1080 IsCorrect = !T.consumeClose() && IsCorrect;
1085 /// \brief Parsing of OpenMP clauses.
1088 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1089 /// default-clause | private-clause | firstprivate-clause | shared-clause
1090 /// | linear-clause | aligned-clause | collapse-clause |
1091 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1092 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1093 /// mergeable-clause | flush-clause | read-clause | write-clause |
1094 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1095 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1096 /// thread_limit-clause | priority-clause | grainsize-clause |
1097 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1098 /// from-clause | is_device_ptr-clause
1100 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1101 OpenMPClauseKind CKind, bool FirstClause) {
1102 OMPClause *Clause = nullptr;
1103 bool ErrorFound = false;
1104 // Check if clause is allowed for the given directive.
1105 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1106 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1107 << getOpenMPDirectiveName(DKind);
1113 case OMPC_num_threads:
1119 case OMPC_num_teams:
1120 case OMPC_thread_limit:
1122 case OMPC_grainsize:
1123 case OMPC_num_tasks:
1125 // OpenMP [2.5, Restrictions]
1126 // At most one num_threads clause can appear on the directive.
1127 // OpenMP [2.8.1, simd construct, Restrictions]
1128 // Only one safelen clause can appear on a simd directive.
1129 // Only one simdlen clause can appear on a simd directive.
1130 // Only one collapse clause can appear on a simd directive.
1131 // OpenMP [2.9.1, target data construct, Restrictions]
1132 // At most one device clause can appear on the directive.
1133 // OpenMP [2.11.1, task Construct, Restrictions]
1134 // At most one if clause can appear on the directive.
1135 // At most one final clause can appear on the directive.
1136 // OpenMP [teams Construct, Restrictions]
1137 // At most one num_teams clause can appear on the directive.
1138 // At most one thread_limit clause can appear on the directive.
1139 // OpenMP [2.9.1, task Construct, Restrictions]
1140 // At most one priority clause can appear on the directive.
1141 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1142 // At most one grainsize clause can appear on the directive.
1143 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1144 // At most one num_tasks clause can appear on the directive.
1146 Diag(Tok, diag::err_omp_more_one_clause)
1147 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1151 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1152 Clause = ParseOpenMPClause(CKind);
1154 Clause = ParseOpenMPSingleExprClause(CKind);
1157 case OMPC_proc_bind:
1158 // OpenMP [2.14.3.1, Restrictions]
1159 // Only a single default clause may be specified on a parallel, task or
1161 // OpenMP [2.5, parallel Construct, Restrictions]
1162 // At most one proc_bind clause can appear on the directive.
1164 Diag(Tok, diag::err_omp_more_one_clause)
1165 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1169 Clause = ParseOpenMPSimpleClause(CKind);
1172 case OMPC_dist_schedule:
1173 case OMPC_defaultmap:
1174 // OpenMP [2.7.1, Restrictions, p. 3]
1175 // Only one schedule clause can appear on a loop directive.
1176 // OpenMP [2.10.4, Restrictions, p. 106]
1177 // At most one defaultmap clause can appear on the directive.
1179 Diag(Tok, diag::err_omp_more_one_clause)
1180 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1185 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1189 case OMPC_mergeable:
1198 // OpenMP [2.7.1, Restrictions, p. 9]
1199 // Only one ordered clause can appear on a loop directive.
1200 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1201 // Only one nowait clause can appear on a for directive.
1203 Diag(Tok, diag::err_omp_more_one_clause)
1204 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1208 Clause = ParseOpenMPClause(CKind);
1211 case OMPC_firstprivate:
1212 case OMPC_lastprivate:
1214 case OMPC_reduction:
1218 case OMPC_copyprivate:
1224 case OMPC_use_device_ptr:
1225 case OMPC_is_device_ptr:
1226 Clause = ParseOpenMPVarListClause(DKind, CKind);
1229 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1230 << getOpenMPDirectiveName(DKind);
1231 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1233 case OMPC_threadprivate:
1235 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1236 << getOpenMPDirectiveName(DKind);
1237 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1240 return ErrorFound ? nullptr : Clause;
1243 /// Parses simple expression in parens for single-expression clauses of OpenMP
1245 /// \param RLoc Returned location of right paren.
1246 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
1247 SourceLocation &RLoc) {
1248 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1249 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1252 SourceLocation ELoc = Tok.getLocation();
1253 ExprResult LHS(ParseCastExpression(
1254 /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1255 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1256 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1261 RLoc = T.getCloseLocation();
1265 /// \brief Parsing of OpenMP clauses with single expressions like 'final',
1266 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1267 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1270 /// 'final' '(' expression ')'
1272 /// num_threads-clause:
1273 /// 'num_threads' '(' expression ')'
1276 /// 'safelen' '(' expression ')'
1279 /// 'simdlen' '(' expression ')'
1281 /// collapse-clause:
1282 /// 'collapse' '(' expression ')'
1284 /// priority-clause:
1285 /// 'priority' '(' expression ')'
1287 /// grainsize-clause:
1288 /// 'grainsize' '(' expression ')'
1290 /// num_tasks-clause:
1291 /// 'num_tasks' '(' expression ')'
1294 /// 'hint' '(' expression ')'
1296 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
1297 SourceLocation Loc = ConsumeToken();
1298 SourceLocation LLoc = Tok.getLocation();
1299 SourceLocation RLoc;
1301 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1303 if (Val.isInvalid())
1306 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1309 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1312 /// 'default' '(' 'none' | 'shared' ')
1314 /// proc_bind-clause:
1315 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1317 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
1318 SourceLocation Loc = Tok.getLocation();
1319 SourceLocation LOpen = ConsumeToken();
1321 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1322 if (T.expectAndConsume(diag::err_expected_lparen_after,
1323 getOpenMPClauseName(Kind)))
1326 unsigned Type = getOpenMPSimpleClauseType(
1327 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1328 SourceLocation TypeLoc = Tok.getLocation();
1329 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1330 Tok.isNot(tok::annot_pragma_openmp_end))
1336 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1340 /// \brief Parsing of OpenMP clauses like 'ordered'.
1351 /// mergeable-clause:
1366 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
1367 SourceLocation Loc = Tok.getLocation();
1370 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1374 /// \brief Parsing of OpenMP clauses with single expressions and some additional
1375 /// argument like 'schedule' or 'dist_schedule'.
1377 /// schedule-clause:
1378 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1382 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1385 /// 'defaultmap' '(' modifier ':' kind ')'
1387 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
1388 SourceLocation Loc = ConsumeToken();
1389 SourceLocation DelimLoc;
1391 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1392 if (T.expectAndConsume(diag::err_expected_lparen_after,
1393 getOpenMPClauseName(Kind)))
1397 SmallVector<unsigned, 4> Arg;
1398 SmallVector<SourceLocation, 4> KLoc;
1399 if (Kind == OMPC_schedule) {
1400 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1401 Arg.resize(NumberOfElements);
1402 KLoc.resize(NumberOfElements);
1403 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1404 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1405 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1406 auto KindModifier = getOpenMPSimpleClauseType(
1407 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1408 if (KindModifier > OMPC_SCHEDULE_unknown) {
1410 Arg[Modifier1] = KindModifier;
1411 KLoc[Modifier1] = Tok.getLocation();
1412 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1413 Tok.isNot(tok::annot_pragma_openmp_end))
1415 if (Tok.is(tok::comma)) {
1416 // Parse ',' 'modifier'
1418 KindModifier = getOpenMPSimpleClauseType(
1419 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1420 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1422 : (unsigned)OMPC_SCHEDULE_unknown;
1423 KLoc[Modifier2] = Tok.getLocation();
1424 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1425 Tok.isNot(tok::annot_pragma_openmp_end))
1429 if (Tok.is(tok::colon))
1432 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1433 KindModifier = getOpenMPSimpleClauseType(
1434 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1436 Arg[ScheduleKind] = KindModifier;
1437 KLoc[ScheduleKind] = Tok.getLocation();
1438 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1439 Tok.isNot(tok::annot_pragma_openmp_end))
1441 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1442 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1443 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1445 DelimLoc = ConsumeAnyToken();
1446 } else if (Kind == OMPC_dist_schedule) {
1447 Arg.push_back(getOpenMPSimpleClauseType(
1448 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1449 KLoc.push_back(Tok.getLocation());
1450 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1451 Tok.isNot(tok::annot_pragma_openmp_end))
1453 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1454 DelimLoc = ConsumeAnyToken();
1455 } else if (Kind == OMPC_defaultmap) {
1456 // Get a defaultmap modifier
1457 Arg.push_back(getOpenMPSimpleClauseType(
1458 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1459 KLoc.push_back(Tok.getLocation());
1460 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1461 Tok.isNot(tok::annot_pragma_openmp_end))
1464 if (Tok.is(tok::colon))
1466 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1467 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1468 // Get a defaultmap kind
1469 Arg.push_back(getOpenMPSimpleClauseType(
1470 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1471 KLoc.push_back(Tok.getLocation());
1472 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1473 Tok.isNot(tok::annot_pragma_openmp_end))
1476 assert(Kind == OMPC_if);
1477 KLoc.push_back(Tok.getLocation());
1478 TentativeParsingAction TPA(*this);
1479 Arg.push_back(ParseOpenMPDirectiveKind(*this));
1480 if (Arg.back() != OMPD_unknown) {
1482 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1484 DelimLoc = ConsumeToken();
1487 Arg.back() = OMPD_unknown;
1493 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1494 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1496 if (NeedAnExpression) {
1497 SourceLocation ELoc = Tok.getLocation();
1498 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
1499 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
1500 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1506 if (NeedAnExpression && Val.isInvalid())
1509 return Actions.ActOnOpenMPSingleExprWithArgClause(
1510 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1511 T.getCloseLocation());
1514 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
1515 UnqualifiedId &ReductionId) {
1516 SourceLocation TemplateKWLoc;
1517 if (ReductionIdScopeSpec.isEmpty()) {
1519 switch (P.getCurToken().getKind()) {
1547 if (OOK != OO_None) {
1548 SourceLocation OpLoc = P.ConsumeToken();
1549 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
1550 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
1554 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
1555 /*AllowDestructorName*/ false,
1556 /*AllowConstructorName*/ false, nullptr,
1557 TemplateKWLoc, ReductionId);
1560 /// Parses clauses with list.
1561 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
1562 OpenMPClauseKind Kind,
1563 SmallVectorImpl<Expr *> &Vars,
1564 OpenMPVarListDataTy &Data) {
1565 UnqualifiedId UnqualifiedReductionId;
1566 bool InvalidReductionId = false;
1567 bool MapTypeModifierSpecified = false;
1570 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1571 if (T.expectAndConsume(diag::err_expected_lparen_after,
1572 getOpenMPClauseName(Kind)))
1575 bool NeedRParenForLinear = false;
1576 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
1577 tok::annot_pragma_openmp_end);
1578 // Handle reduction-identifier for reduction clause.
1579 if (Kind == OMPC_reduction) {
1580 ColonProtectionRAIIObject ColonRAII(*this);
1581 if (getLangOpts().CPlusPlus)
1582 ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
1583 /*ObjectType=*/nullptr,
1584 /*EnteringContext=*/false);
1585 InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
1586 UnqualifiedReductionId);
1587 if (InvalidReductionId) {
1588 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1591 if (Tok.is(tok::colon))
1592 Data.ColonLoc = ConsumeToken();
1594 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
1595 if (!InvalidReductionId)
1597 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1598 } else if (Kind == OMPC_depend) {
1599 // Handle dependency type for depend clause.
1600 ColonProtectionRAIIObject ColonRAII(*this);
1602 static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
1603 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
1604 Data.DepLinMapLoc = Tok.getLocation();
1606 if (Data.DepKind == OMPC_DEPEND_unknown) {
1607 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1611 // Special processing for depend(source) clause.
1612 if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
1618 if (Tok.is(tok::colon))
1619 Data.ColonLoc = ConsumeToken();
1621 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1622 : diag::warn_pragma_expected_colon)
1623 << "dependency type";
1625 } else if (Kind == OMPC_linear) {
1626 // Try to parse modifier if any.
1627 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
1628 Data.LinKind = static_cast<OpenMPLinearClauseKind>(
1629 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
1630 Data.DepLinMapLoc = ConsumeToken();
1631 LinearT.consumeOpen();
1632 NeedRParenForLinear = true;
1634 } else if (Kind == OMPC_map) {
1635 // Handle map type for map clause.
1636 ColonProtectionRAIIObject ColonRAII(*this);
1638 /// The map clause modifier token can be either a identifier or the C++
1640 auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
1641 return Tok.isOneOf(tok::identifier, tok::kw_delete);
1644 // The first identifier may be a list item, a map-type or a
1645 // map-type-modifier. The map modifier can also be delete which has the same
1646 // spelling of the C++ delete keyword.
1648 IsMapClauseModifierToken(Tok)
1649 ? static_cast<OpenMPMapClauseKind>(
1650 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1652 Data.DepLinMapLoc = Tok.getLocation();
1653 bool ColonExpected = false;
1655 if (IsMapClauseModifierToken(Tok)) {
1656 if (PP.LookAhead(0).is(tok::colon)) {
1657 if (Data.MapType == OMPC_MAP_unknown)
1658 Diag(Tok, diag::err_omp_unknown_map_type);
1659 else if (Data.MapType == OMPC_MAP_always)
1660 Diag(Tok, diag::err_omp_map_type_missing);
1662 } else if (PP.LookAhead(0).is(tok::comma)) {
1663 if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
1664 PP.LookAhead(2).is(tok::colon)) {
1665 Data.MapTypeModifier = Data.MapType;
1666 if (Data.MapTypeModifier != OMPC_MAP_always) {
1667 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1668 Data.MapTypeModifier = OMPC_MAP_unknown;
1670 MapTypeModifierSpecified = true;
1676 IsMapClauseModifierToken(Tok)
1677 ? static_cast<OpenMPMapClauseKind>(
1678 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1680 if (Data.MapType == OMPC_MAP_unknown ||
1681 Data.MapType == OMPC_MAP_always)
1682 Diag(Tok, diag::err_omp_unknown_map_type);
1685 Data.MapType = OMPC_MAP_tofrom;
1686 Data.IsMapTypeImplicit = true;
1689 Data.MapType = OMPC_MAP_tofrom;
1690 Data.IsMapTypeImplicit = true;
1693 Data.MapType = OMPC_MAP_tofrom;
1694 Data.IsMapTypeImplicit = true;
1697 if (Tok.is(tok::colon))
1698 Data.ColonLoc = ConsumeToken();
1699 else if (ColonExpected)
1700 Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
1704 (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
1705 (Kind == OMPC_reduction && !InvalidReductionId) ||
1706 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
1707 (!MapTypeModifierSpecified ||
1708 Data.MapTypeModifier == OMPC_MAP_always)) ||
1709 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
1710 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1711 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
1712 Tok.isNot(tok::annot_pragma_openmp_end))) {
1713 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
1715 ExprResult VarExpr =
1716 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
1717 if (VarExpr.isUsable())
1718 Vars.push_back(VarExpr.get());
1720 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1724 IsComma = Tok.is(tok::comma);
1727 else if (Tok.isNot(tok::r_paren) &&
1728 Tok.isNot(tok::annot_pragma_openmp_end) &&
1729 (!MayHaveTail || Tok.isNot(tok::colon)))
1730 Diag(Tok, diag::err_omp_expected_punc)
1731 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
1732 : getOpenMPClauseName(Kind))
1733 << (Kind == OMPC_flush);
1736 // Parse ')' for linear clause with modifier.
1737 if (NeedRParenForLinear)
1738 LinearT.consumeClose();
1740 // Parse ':' linear-step (or ':' alignment).
1741 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
1743 Data.ColonLoc = Tok.getLocation();
1744 SourceLocation ELoc = ConsumeToken();
1745 ExprResult Tail = ParseAssignmentExpression();
1746 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
1747 if (Tail.isUsable())
1748 Data.TailExpr = Tail.get();
1750 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1756 if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
1758 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1759 (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
1764 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
1765 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
1768 /// 'private' '(' list ')'
1769 /// firstprivate-clause:
1770 /// 'firstprivate' '(' list ')'
1771 /// lastprivate-clause:
1772 /// 'lastprivate' '(' list ')'
1774 /// 'shared' '(' list ')'
1776 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
1778 /// 'aligned' '(' list [ ':' alignment ] ')'
1779 /// reduction-clause:
1780 /// 'reduction' '(' reduction-identifier ':' list ')'
1781 /// copyprivate-clause:
1782 /// 'copyprivate' '(' list ')'
1784 /// 'flush' '(' list ')'
1786 /// 'depend' '(' in | out | inout : list | source ')'
1788 /// 'map' '(' [ [ always , ]
1789 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
1791 /// 'to' '(' list ')'
1793 /// 'from' '(' list ')'
1794 /// use_device_ptr-clause:
1795 /// 'use_device_ptr' '(' list ')'
1796 /// is_device_ptr-clause:
1797 /// 'is_device_ptr' '(' list ')'
1799 /// For 'linear' clause linear-list may have the following forms:
1802 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
1803 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
1804 OpenMPClauseKind Kind) {
1805 SourceLocation Loc = Tok.getLocation();
1806 SourceLocation LOpen = ConsumeToken();
1807 SmallVector<Expr *, 4> Vars;
1808 OpenMPVarListDataTy Data;
1810 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
1813 return Actions.ActOnOpenMPVarListClause(
1814 Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
1815 Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1816 Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,