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::OpenMPDirectiveScope);
306 // Parse <combiner> expression.
307 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
308 ExprResult CombinerResult =
309 Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
310 D->getLocation(), /*DiscardedValue=*/true);
311 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
313 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
314 Tok.isNot(tok::annot_pragma_openmp_end)) {
319 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
320 ExprResult InitializerResult;
321 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
322 // Parse <initializer> expression.
323 if (Tok.is(tok::identifier) &&
324 Tok.getIdentifierInfo()->isStr("initializer"))
327 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
333 BalancedDelimiterTracker T(*this, tok::l_paren,
334 tok::annot_pragma_openmp_end);
336 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
338 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
339 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
340 Scope::OpenMPDirectiveScope);
342 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
343 InitializerResult = Actions.ActOnFinishFullExpr(
344 ParseAssignmentExpression().get(), D->getLocation(),
345 /*DiscardedValue=*/true);
346 Actions.ActOnOpenMPDeclareReductionInitializerEnd(
347 D, InitializerResult.get());
348 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
349 Tok.isNot(tok::annot_pragma_openmp_end)) {
355 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
360 // Revert parsing if not the last type, otherwise accept it, we're done with
367 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
372 /// RAII that recreates function context for correct parsing of clauses of
373 /// 'declare simd' construct.
374 /// OpenMP, 2.8.2 declare simd Construct
375 /// The expressions appearing in the clauses of this directive are evaluated in
376 /// the scope of the arguments of the function declaration or definition.
377 class FNContextRAII final {
379 Sema::CXXThisScopeRAII *ThisScope;
380 Parser::ParseScope *TempScope;
381 Parser::ParseScope *FnScope;
382 bool HasTemplateScope = false;
383 bool HasFunScope = false;
384 FNContextRAII() = delete;
385 FNContextRAII(const FNContextRAII &) = delete;
386 FNContextRAII &operator=(const FNContextRAII &) = delete;
389 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
390 Decl *D = *Ptr.get().begin();
391 NamedDecl *ND = dyn_cast<NamedDecl>(D);
392 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
393 Sema &Actions = P.getActions();
395 // Allow 'this' within late-parsed attributes.
396 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
397 ND && ND->isCXXInstanceMember());
399 // If the Decl is templatized, add template parameters to scope.
400 HasTemplateScope = D->isTemplateDecl();
402 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
403 if (HasTemplateScope)
404 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
406 // If the Decl is on a function, add function parameters to the scope.
407 HasFunScope = D->isFunctionOrFunctionTemplate();
408 FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
411 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
415 P.getActions().ActOnExitFunctionContext();
416 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
418 if (HasTemplateScope)
427 /// Parses clauses for 'declare simd' directive.
429 /// 'inbranch' | 'notinbranch'
430 /// 'simdlen' '(' <expr> ')'
431 /// { 'uniform' '(' <argument_list> ')' }
432 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
433 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
434 static bool parseDeclareSimdClauses(
435 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
436 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
437 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
438 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
440 const Token &Tok = P.getCurToken();
441 bool IsError = false;
442 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
443 if (Tok.isNot(tok::identifier))
445 OMPDeclareSimdDeclAttr::BranchStateTy Out;
446 IdentifierInfo *II = Tok.getIdentifierInfo();
447 StringRef ClauseName = II->getName();
448 // Parse 'inranch|notinbranch' clauses.
449 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
450 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
451 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
453 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
457 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
459 } else if (ClauseName.equals("simdlen")) {
460 if (SimdLen.isUsable()) {
461 P.Diag(Tok, diag::err_omp_more_one_clause)
462 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
467 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
468 if (SimdLen.isInvalid())
471 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
472 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
473 CKind == OMPC_linear) {
474 Parser::OpenMPVarListDataTy Data;
475 auto *Vars = &Uniforms;
476 if (CKind == OMPC_aligned)
478 else if (CKind == OMPC_linear)
482 if (P.ParseOpenMPVarList(OMPD_declare_simd,
483 getOpenMPClauseKind(ClauseName), *Vars, Data))
485 if (CKind == OMPC_aligned)
486 Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
487 else if (CKind == OMPC_linear) {
488 if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
490 Data.LinKind = OMPC_LINEAR_val;
491 LinModifiers.append(Linears.size() - LinModifiers.size(),
493 Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
496 // TODO: add parsing of other clauses.
500 if (Tok.is(tok::comma))
506 /// Parse clauses for '#pragma omp declare simd'.
507 Parser::DeclGroupPtrTy
508 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
509 CachedTokens &Toks, SourceLocation Loc) {
511 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
512 // Consume the previously pushed token.
513 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
515 FNContextRAII FnContext(*this, Ptr);
516 OMPDeclareSimdDeclAttr::BranchStateTy BS =
517 OMPDeclareSimdDeclAttr::BS_Undefined;
519 SmallVector<Expr *, 4> Uniforms;
520 SmallVector<Expr *, 4> Aligneds;
521 SmallVector<Expr *, 4> Alignments;
522 SmallVector<Expr *, 4> Linears;
523 SmallVector<unsigned, 4> LinModifiers;
524 SmallVector<Expr *, 4> Steps;
526 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
527 Alignments, Linears, LinModifiers, Steps);
528 // Need to check for extra tokens.
529 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
530 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
531 << getOpenMPDirectiveName(OMPD_declare_simd);
532 while (Tok.isNot(tok::annot_pragma_openmp_end))
535 // Skip the last annot_pragma_openmp_end.
536 SourceLocation EndLoc = ConsumeAnnotationToken();
538 return Actions.ActOnOpenMPDeclareSimdDirective(
539 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
540 LinModifiers, Steps, SourceRange(Loc, EndLoc));
545 /// \brief Parsing of declarative OpenMP directives.
547 /// threadprivate-directive:
548 /// annot_pragma_openmp 'threadprivate' simple-variable-list
549 /// annot_pragma_openmp_end
551 /// declare-reduction-directive:
552 /// annot_pragma_openmp 'declare' 'reduction' [...]
553 /// annot_pragma_openmp_end
555 /// declare-simd-directive:
556 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
557 /// annot_pragma_openmp_end
558 /// <function declaration/definition>
560 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
561 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
562 DeclSpec::TST TagType, Decl *Tag) {
563 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
564 ParenBraceBracketBalancer BalancerRAIIObj(*this);
566 SourceLocation Loc = ConsumeAnnotationToken();
567 auto DKind = ParseOpenMPDirectiveKind(*this);
570 case OMPD_threadprivate: {
572 ThreadprivateListParserHelper Helper(this);
573 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
574 // The last seen token is annot_pragma_openmp_end - need to check for
576 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
577 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
578 << getOpenMPDirectiveName(OMPD_threadprivate);
579 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
581 // Skip the last annot_pragma_openmp_end.
582 ConsumeAnnotationToken();
583 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
584 Helper.getIdentifiers());
588 case OMPD_declare_reduction:
590 if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
591 // The last seen token is annot_pragma_openmp_end - need to check for
593 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
594 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
595 << getOpenMPDirectiveName(OMPD_declare_reduction);
596 while (Tok.isNot(tok::annot_pragma_openmp_end))
599 // Skip the last annot_pragma_openmp_end.
600 ConsumeAnnotationToken();
604 case OMPD_declare_simd: {
606 // { #pragma omp declare simd }
607 // <function-declaration-or-definition>
611 while(Tok.isNot(tok::annot_pragma_openmp_end)) {
619 if (Tok.is(tok::annot_pragma_openmp))
620 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
621 else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
622 // Here we expect to see some function declaration.
624 assert(TagType == DeclSpec::TST_unspecified);
625 MaybeParseCXX11Attributes(Attrs);
626 ParsingDeclSpec PDS(*this);
627 Ptr = ParseExternalDeclaration(Attrs, &PDS);
630 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
634 Diag(Loc, diag::err_omp_decl_in_declare_simd);
635 return DeclGroupPtrTy();
637 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
639 case OMPD_declare_target: {
640 SourceLocation DTLoc = ConsumeAnyToken();
641 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
642 // OpenMP 4.5 syntax with list of entities.
643 llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
644 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
645 OMPDeclareTargetDeclAttr::MapTypeTy MT =
646 OMPDeclareTargetDeclAttr::MT_To;
647 if (Tok.is(tok::identifier)) {
648 IdentifierInfo *II = Tok.getIdentifierInfo();
649 StringRef ClauseName = II->getName();
650 // Parse 'to|link' clauses.
651 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
653 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
659 auto Callback = [this, MT, &SameDirectiveDecls](
660 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
661 Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
664 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
667 // Consume optional ','.
668 if (Tok.is(tok::comma))
671 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
673 return DeclGroupPtrTy();
676 // Skip the last annot_pragma_openmp_end.
679 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
680 return DeclGroupPtrTy();
682 DKind = ParseOpenMPDirectiveKind(*this);
683 while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
684 Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
685 ParsedAttributesWithRange attrs(AttrFactory);
686 MaybeParseCXX11Attributes(attrs);
687 ParseExternalDeclaration(attrs);
688 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
689 TentativeParsingAction TPA(*this);
690 ConsumeAnnotationToken();
691 DKind = ParseOpenMPDirectiveKind(*this);
692 if (DKind != OMPD_end_declare_target)
699 if (DKind == OMPD_end_declare_target) {
701 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
702 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
703 << getOpenMPDirectiveName(OMPD_end_declare_target);
704 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
706 // Skip the last annot_pragma_openmp_end.
709 Diag(Tok, diag::err_expected_end_declare_target);
710 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
712 Actions.ActOnFinishOpenMPDeclareTargetDirective();
713 return DeclGroupPtrTy();
716 Diag(Tok, diag::err_omp_unknown_directive);
734 case OMPD_parallel_for:
735 case OMPD_parallel_for_simd:
736 case OMPD_parallel_sections:
740 case OMPD_cancellation_point:
742 case OMPD_target_data:
743 case OMPD_target_enter_data:
744 case OMPD_target_exit_data:
745 case OMPD_target_parallel:
746 case OMPD_target_parallel_for:
748 case OMPD_taskloop_simd:
749 case OMPD_distribute:
750 case OMPD_end_declare_target:
751 case OMPD_target_update:
752 case OMPD_distribute_parallel_for:
753 case OMPD_distribute_parallel_for_simd:
754 case OMPD_distribute_simd:
755 case OMPD_target_parallel_for_simd:
756 case OMPD_target_simd:
757 case OMPD_teams_distribute:
758 case OMPD_teams_distribute_simd:
759 case OMPD_teams_distribute_parallel_for_simd:
760 case OMPD_teams_distribute_parallel_for:
761 case OMPD_target_teams:
762 case OMPD_target_teams_distribute:
763 case OMPD_target_teams_distribute_parallel_for:
764 case OMPD_target_teams_distribute_parallel_for_simd:
765 case OMPD_target_teams_distribute_simd:
766 Diag(Tok, diag::err_omp_unexpected_directive)
767 << getOpenMPDirectiveName(DKind);
770 while (Tok.isNot(tok::annot_pragma_openmp_end))
776 /// \brief Parsing of declarative or executable OpenMP directives.
778 /// threadprivate-directive:
779 /// annot_pragma_openmp 'threadprivate' simple-variable-list
780 /// annot_pragma_openmp_end
782 /// declare-reduction-directive:
783 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
784 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
785 /// ('omp_priv' '=' <expression>|<function_call>) ')']
786 /// annot_pragma_openmp_end
788 /// executable-directive:
789 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
790 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
791 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
792 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
793 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
794 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
795 /// 'distribute' | 'target enter data' | 'target exit data' |
796 /// 'target parallel' | 'target parallel for' |
797 /// 'target update' | 'distribute parallel for' |
798 /// 'distribute paralle for simd' | 'distribute simd' |
799 /// 'target parallel for simd' | 'target simd' |
800 /// 'teams distribute' | 'teams distribute simd' |
801 /// 'teams distribute parallel for simd' |
802 /// 'teams distribute parallel for' | 'target teams' |
803 /// 'target teams distribute' |
804 /// 'target teams distribute parallel for' |
805 /// 'target teams distribute parallel for simd' |
806 /// 'target teams distribute simd' {clause}
807 /// annot_pragma_openmp_end
809 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
810 AllowedConstructsKind Allowed) {
811 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
812 ParenBraceBracketBalancer BalancerRAIIObj(*this);
813 SmallVector<OMPClause *, 5> Clauses;
814 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
815 FirstClauses(OMPC_unknown + 1);
816 unsigned ScopeFlags =
817 Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
818 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
819 auto DKind = ParseOpenMPDirectiveKind(*this);
820 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
821 // Name of critical directive.
822 DeclarationNameInfo DirName;
823 StmtResult Directive = StmtError();
824 bool HasAssociatedStatement = true;
825 bool FlushHasClause = false;
828 case OMPD_threadprivate: {
829 if (Allowed != ACK_Any) {
830 Diag(Tok, diag::err_omp_immediate_directive)
831 << getOpenMPDirectiveName(DKind) << 0;
834 ThreadprivateListParserHelper Helper(this);
835 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
836 // The last seen token is annot_pragma_openmp_end - need to check for
838 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
839 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
840 << getOpenMPDirectiveName(OMPD_threadprivate);
841 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
843 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
844 Loc, Helper.getIdentifiers());
845 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
847 SkipUntil(tok::annot_pragma_openmp_end);
850 case OMPD_declare_reduction:
852 if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
853 // The last seen token is annot_pragma_openmp_end - need to check for
855 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
856 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
857 << getOpenMPDirectiveName(OMPD_declare_reduction);
858 while (Tok.isNot(tok::annot_pragma_openmp_end))
862 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
864 SkipUntil(tok::annot_pragma_openmp_end);
867 if (PP.LookAhead(0).is(tok::l_paren)) {
868 FlushHasClause = true;
869 // Push copy of the current token back to stream to properly parse
870 // pseudo-clause OMPFlushClause.
877 case OMPD_cancellation_point:
879 case OMPD_target_enter_data:
880 case OMPD_target_exit_data:
881 case OMPD_target_update:
882 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
883 Diag(Tok, diag::err_omp_immediate_directive)
884 << getOpenMPDirectiveName(DKind) << 0;
886 HasAssociatedStatement = false;
887 // Fall through for further analysis.
898 case OMPD_parallel_for:
899 case OMPD_parallel_for_simd:
900 case OMPD_parallel_sections:
907 case OMPD_target_data:
908 case OMPD_target_parallel:
909 case OMPD_target_parallel_for:
911 case OMPD_taskloop_simd:
912 case OMPD_distribute:
913 case OMPD_distribute_parallel_for:
914 case OMPD_distribute_parallel_for_simd:
915 case OMPD_distribute_simd:
916 case OMPD_target_parallel_for_simd:
917 case OMPD_target_simd:
918 case OMPD_teams_distribute:
919 case OMPD_teams_distribute_simd:
920 case OMPD_teams_distribute_parallel_for_simd:
921 case OMPD_teams_distribute_parallel_for:
922 case OMPD_target_teams:
923 case OMPD_target_teams_distribute:
924 case OMPD_target_teams_distribute_parallel_for:
925 case OMPD_target_teams_distribute_parallel_for_simd:
926 case OMPD_target_teams_distribute_simd: {
928 // Parse directive name of the 'critical' directive if any.
929 if (DKind == OMPD_critical) {
930 BalancedDelimiterTracker T(*this, tok::l_paren,
931 tok::annot_pragma_openmp_end);
932 if (!T.consumeOpen()) {
933 if (Tok.isAnyIdentifier()) {
935 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
938 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
942 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
943 CancelRegion = ParseOpenMPDirectiveKind(*this);
944 if (Tok.isNot(tok::annot_pragma_openmp_end))
948 if (isOpenMPLoopDirective(DKind))
949 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
950 if (isOpenMPSimdDirective(DKind))
951 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
952 ParseScope OMPDirectiveScope(this, ScopeFlags);
953 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
955 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
956 OpenMPClauseKind CKind =
959 : FlushHasClause ? OMPC_flush
960 : getOpenMPClauseKind(PP.getSpelling(Tok));
961 Actions.StartOpenMPClause(CKind);
962 FlushHasClause = false;
964 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
965 FirstClauses[CKind].setInt(true);
967 FirstClauses[CKind].setPointer(Clause);
968 Clauses.push_back(Clause);
972 if (Tok.is(tok::comma))
974 Actions.EndOpenMPClause();
976 // End location of the directive.
977 EndLoc = Tok.getLocation();
978 // Consume final annot_pragma_openmp_end.
979 ConsumeAnnotationToken();
981 // OpenMP [2.13.8, ordered Construct, Syntax]
982 // If the depend clause is specified, the ordered construct is a stand-alone
984 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
985 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
986 Diag(Loc, diag::err_omp_immediate_directive)
987 << getOpenMPDirectiveName(DKind) << 1
988 << getOpenMPClauseName(OMPC_depend);
990 HasAssociatedStatement = false;
993 StmtResult AssociatedStmt;
994 if (HasAssociatedStatement) {
995 // The body is a block scope like in Lambdas and Blocks.
996 Sema::CompoundScopeRAII CompoundScope(Actions);
997 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
998 Actions.ActOnStartOfCompoundStmt();
1000 AssociatedStmt = ParseStatement();
1001 Actions.ActOnFinishOfCompoundStmt();
1002 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1004 Directive = Actions.ActOnOpenMPExecutableDirective(
1005 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1009 Actions.EndOpenMPDSABlock(Directive.get());
1010 OMPDirectiveScope.Exit();
1013 case OMPD_declare_simd:
1014 case OMPD_declare_target:
1015 case OMPD_end_declare_target:
1016 Diag(Tok, diag::err_omp_unexpected_directive)
1017 << getOpenMPDirectiveName(DKind);
1018 SkipUntil(tok::annot_pragma_openmp_end);
1021 Diag(Tok, diag::err_omp_unknown_directive);
1022 SkipUntil(tok::annot_pragma_openmp_end);
1028 // Parses simple list:
1029 // simple-variable-list:
1030 // '(' id-expression {, id-expression} ')'
1032 bool Parser::ParseOpenMPSimpleVarList(
1033 OpenMPDirectiveKind Kind,
1034 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1036 bool AllowScopeSpecifier) {
1038 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1039 if (T.expectAndConsume(diag::err_expected_lparen_after,
1040 getOpenMPDirectiveName(Kind)))
1042 bool IsCorrect = true;
1043 bool NoIdentIsFound = true;
1045 // Read tokens while ')' or annot_pragma_openmp_end is not found.
1046 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1048 SourceLocation TemplateKWLoc;
1051 Token PrevTok = Tok;
1052 NoIdentIsFound = false;
1054 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1055 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1057 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1059 } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1060 TemplateKWLoc, Name)) {
1062 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1064 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1065 Tok.isNot(tok::annot_pragma_openmp_end)) {
1067 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1069 Diag(PrevTok.getLocation(), diag::err_expected)
1071 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1073 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1076 if (Tok.is(tok::comma)) {
1081 if (NoIdentIsFound) {
1082 Diag(Tok, diag::err_expected) << tok::identifier;
1087 IsCorrect = !T.consumeClose() && IsCorrect;
1092 /// \brief Parsing of OpenMP clauses.
1095 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1096 /// default-clause | private-clause | firstprivate-clause | shared-clause
1097 /// | linear-clause | aligned-clause | collapse-clause |
1098 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1099 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1100 /// mergeable-clause | flush-clause | read-clause | write-clause |
1101 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1102 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1103 /// thread_limit-clause | priority-clause | grainsize-clause |
1104 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1105 /// from-clause | is_device_ptr-clause | task_reduction-clause
1107 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1108 OpenMPClauseKind CKind, bool FirstClause) {
1109 OMPClause *Clause = nullptr;
1110 bool ErrorFound = false;
1111 // Check if clause is allowed for the given directive.
1112 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1113 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1114 << getOpenMPDirectiveName(DKind);
1120 case OMPC_num_threads:
1126 case OMPC_num_teams:
1127 case OMPC_thread_limit:
1129 case OMPC_grainsize:
1130 case OMPC_num_tasks:
1132 // OpenMP [2.5, Restrictions]
1133 // At most one num_threads clause can appear on the directive.
1134 // OpenMP [2.8.1, simd construct, Restrictions]
1135 // Only one safelen clause can appear on a simd directive.
1136 // Only one simdlen clause can appear on a simd directive.
1137 // Only one collapse clause can appear on a simd directive.
1138 // OpenMP [2.9.1, target data construct, Restrictions]
1139 // At most one device clause can appear on the directive.
1140 // OpenMP [2.11.1, task Construct, Restrictions]
1141 // At most one if clause can appear on the directive.
1142 // At most one final clause can appear on the directive.
1143 // OpenMP [teams Construct, Restrictions]
1144 // At most one num_teams clause can appear on the directive.
1145 // At most one thread_limit clause can appear on the directive.
1146 // OpenMP [2.9.1, task Construct, Restrictions]
1147 // At most one priority clause can appear on the directive.
1148 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1149 // At most one grainsize clause can appear on the directive.
1150 // OpenMP [2.9.2, taskloop Construct, Restrictions]
1151 // At most one num_tasks clause can appear on the directive.
1153 Diag(Tok, diag::err_omp_more_one_clause)
1154 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1158 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1159 Clause = ParseOpenMPClause(CKind);
1161 Clause = ParseOpenMPSingleExprClause(CKind);
1164 case OMPC_proc_bind:
1165 // OpenMP [2.14.3.1, Restrictions]
1166 // Only a single default clause may be specified on a parallel, task or
1168 // OpenMP [2.5, parallel Construct, Restrictions]
1169 // At most one proc_bind clause can appear on the directive.
1171 Diag(Tok, diag::err_omp_more_one_clause)
1172 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1176 Clause = ParseOpenMPSimpleClause(CKind);
1179 case OMPC_dist_schedule:
1180 case OMPC_defaultmap:
1181 // OpenMP [2.7.1, Restrictions, p. 3]
1182 // Only one schedule clause can appear on a loop directive.
1183 // OpenMP [2.10.4, Restrictions, p. 106]
1184 // At most one defaultmap clause can appear on the directive.
1186 Diag(Tok, diag::err_omp_more_one_clause)
1187 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1193 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1197 case OMPC_mergeable:
1206 // OpenMP [2.7.1, Restrictions, p. 9]
1207 // Only one ordered clause can appear on a loop directive.
1208 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1209 // Only one nowait clause can appear on a for directive.
1211 Diag(Tok, diag::err_omp_more_one_clause)
1212 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1216 Clause = ParseOpenMPClause(CKind);
1219 case OMPC_firstprivate:
1220 case OMPC_lastprivate:
1222 case OMPC_reduction:
1223 case OMPC_task_reduction:
1227 case OMPC_copyprivate:
1233 case OMPC_use_device_ptr:
1234 case OMPC_is_device_ptr:
1235 Clause = ParseOpenMPVarListClause(DKind, CKind);
1238 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1239 << getOpenMPDirectiveName(DKind);
1240 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1242 case OMPC_threadprivate:
1244 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1245 << getOpenMPDirectiveName(DKind);
1246 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1249 return ErrorFound ? nullptr : Clause;
1252 /// Parses simple expression in parens for single-expression clauses of OpenMP
1254 /// \param RLoc Returned location of right paren.
1255 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
1256 SourceLocation &RLoc) {
1257 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1258 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1261 SourceLocation ELoc = Tok.getLocation();
1262 ExprResult LHS(ParseCastExpression(
1263 /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1264 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1265 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1270 RLoc = T.getCloseLocation();
1274 /// \brief Parsing of OpenMP clauses with single expressions like 'final',
1275 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1276 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1279 /// 'final' '(' expression ')'
1281 /// num_threads-clause:
1282 /// 'num_threads' '(' expression ')'
1285 /// 'safelen' '(' expression ')'
1288 /// 'simdlen' '(' expression ')'
1290 /// collapse-clause:
1291 /// 'collapse' '(' expression ')'
1293 /// priority-clause:
1294 /// 'priority' '(' expression ')'
1296 /// grainsize-clause:
1297 /// 'grainsize' '(' expression ')'
1299 /// num_tasks-clause:
1300 /// 'num_tasks' '(' expression ')'
1303 /// 'hint' '(' expression ')'
1305 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
1306 SourceLocation Loc = ConsumeToken();
1307 SourceLocation LLoc = Tok.getLocation();
1308 SourceLocation RLoc;
1310 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1312 if (Val.isInvalid())
1315 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1318 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1321 /// 'default' '(' 'none' | 'shared' ')
1323 /// proc_bind-clause:
1324 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1326 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
1327 SourceLocation Loc = Tok.getLocation();
1328 SourceLocation LOpen = ConsumeToken();
1330 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1331 if (T.expectAndConsume(diag::err_expected_lparen_after,
1332 getOpenMPClauseName(Kind)))
1335 unsigned Type = getOpenMPSimpleClauseType(
1336 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1337 SourceLocation TypeLoc = Tok.getLocation();
1338 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1339 Tok.isNot(tok::annot_pragma_openmp_end))
1345 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1349 /// \brief Parsing of OpenMP clauses like 'ordered'.
1360 /// mergeable-clause:
1375 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
1376 SourceLocation Loc = Tok.getLocation();
1379 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1383 /// \brief Parsing of OpenMP clauses with single expressions and some additional
1384 /// argument like 'schedule' or 'dist_schedule'.
1386 /// schedule-clause:
1387 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1391 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1394 /// 'defaultmap' '(' modifier ':' kind ')'
1396 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
1397 SourceLocation Loc = ConsumeToken();
1398 SourceLocation DelimLoc;
1400 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1401 if (T.expectAndConsume(diag::err_expected_lparen_after,
1402 getOpenMPClauseName(Kind)))
1406 SmallVector<unsigned, 4> Arg;
1407 SmallVector<SourceLocation, 4> KLoc;
1408 if (Kind == OMPC_schedule) {
1409 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1410 Arg.resize(NumberOfElements);
1411 KLoc.resize(NumberOfElements);
1412 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1413 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1414 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1415 auto KindModifier = getOpenMPSimpleClauseType(
1416 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1417 if (KindModifier > OMPC_SCHEDULE_unknown) {
1419 Arg[Modifier1] = KindModifier;
1420 KLoc[Modifier1] = Tok.getLocation();
1421 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1422 Tok.isNot(tok::annot_pragma_openmp_end))
1424 if (Tok.is(tok::comma)) {
1425 // Parse ',' 'modifier'
1427 KindModifier = getOpenMPSimpleClauseType(
1428 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1429 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1431 : (unsigned)OMPC_SCHEDULE_unknown;
1432 KLoc[Modifier2] = Tok.getLocation();
1433 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1434 Tok.isNot(tok::annot_pragma_openmp_end))
1438 if (Tok.is(tok::colon))
1441 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1442 KindModifier = getOpenMPSimpleClauseType(
1443 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1445 Arg[ScheduleKind] = KindModifier;
1446 KLoc[ScheduleKind] = Tok.getLocation();
1447 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1448 Tok.isNot(tok::annot_pragma_openmp_end))
1450 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1451 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1452 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1454 DelimLoc = ConsumeAnyToken();
1455 } else if (Kind == OMPC_dist_schedule) {
1456 Arg.push_back(getOpenMPSimpleClauseType(
1457 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1458 KLoc.push_back(Tok.getLocation());
1459 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1460 Tok.isNot(tok::annot_pragma_openmp_end))
1462 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1463 DelimLoc = ConsumeAnyToken();
1464 } else if (Kind == OMPC_defaultmap) {
1465 // Get a defaultmap modifier
1466 Arg.push_back(getOpenMPSimpleClauseType(
1467 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1468 KLoc.push_back(Tok.getLocation());
1469 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1470 Tok.isNot(tok::annot_pragma_openmp_end))
1473 if (Tok.is(tok::colon))
1475 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1476 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1477 // Get a defaultmap kind
1478 Arg.push_back(getOpenMPSimpleClauseType(
1479 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1480 KLoc.push_back(Tok.getLocation());
1481 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1482 Tok.isNot(tok::annot_pragma_openmp_end))
1485 assert(Kind == OMPC_if);
1486 KLoc.push_back(Tok.getLocation());
1487 TentativeParsingAction TPA(*this);
1488 Arg.push_back(ParseOpenMPDirectiveKind(*this));
1489 if (Arg.back() != OMPD_unknown) {
1491 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1493 DelimLoc = ConsumeToken();
1496 Arg.back() = OMPD_unknown;
1502 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1503 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1505 if (NeedAnExpression) {
1506 SourceLocation ELoc = Tok.getLocation();
1507 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
1508 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
1509 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1515 if (NeedAnExpression && Val.isInvalid())
1518 return Actions.ActOnOpenMPSingleExprWithArgClause(
1519 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1520 T.getCloseLocation());
1523 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
1524 UnqualifiedId &ReductionId) {
1525 SourceLocation TemplateKWLoc;
1526 if (ReductionIdScopeSpec.isEmpty()) {
1528 switch (P.getCurToken().getKind()) {
1556 if (OOK != OO_None) {
1557 SourceLocation OpLoc = P.ConsumeToken();
1558 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
1559 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
1563 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
1564 /*AllowDestructorName*/ false,
1565 /*AllowConstructorName*/ false,
1566 /*AllowDeductionGuide*/ false,
1567 nullptr, TemplateKWLoc, ReductionId);
1570 /// Parses clauses with list.
1571 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
1572 OpenMPClauseKind Kind,
1573 SmallVectorImpl<Expr *> &Vars,
1574 OpenMPVarListDataTy &Data) {
1575 UnqualifiedId UnqualifiedReductionId;
1576 bool InvalidReductionId = false;
1577 bool MapTypeModifierSpecified = false;
1580 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1581 if (T.expectAndConsume(diag::err_expected_lparen_after,
1582 getOpenMPClauseName(Kind)))
1585 bool NeedRParenForLinear = false;
1586 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
1587 tok::annot_pragma_openmp_end);
1588 // Handle reduction-identifier for reduction clause.
1589 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) {
1590 ColonProtectionRAIIObject ColonRAII(*this);
1591 if (getLangOpts().CPlusPlus)
1592 ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
1593 /*ObjectType=*/nullptr,
1594 /*EnteringContext=*/false);
1595 InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
1596 UnqualifiedReductionId);
1597 if (InvalidReductionId) {
1598 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1601 if (Tok.is(tok::colon))
1602 Data.ColonLoc = ConsumeToken();
1604 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
1605 if (!InvalidReductionId)
1607 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1608 } else if (Kind == OMPC_depend) {
1609 // Handle dependency type for depend clause.
1610 ColonProtectionRAIIObject ColonRAII(*this);
1612 static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
1613 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
1614 Data.DepLinMapLoc = Tok.getLocation();
1616 if (Data.DepKind == OMPC_DEPEND_unknown) {
1617 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1621 // Special processing for depend(source) clause.
1622 if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
1628 if (Tok.is(tok::colon))
1629 Data.ColonLoc = ConsumeToken();
1631 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1632 : diag::warn_pragma_expected_colon)
1633 << "dependency type";
1635 } else if (Kind == OMPC_linear) {
1636 // Try to parse modifier if any.
1637 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
1638 Data.LinKind = static_cast<OpenMPLinearClauseKind>(
1639 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
1640 Data.DepLinMapLoc = ConsumeToken();
1641 LinearT.consumeOpen();
1642 NeedRParenForLinear = true;
1644 } else if (Kind == OMPC_map) {
1645 // Handle map type for map clause.
1646 ColonProtectionRAIIObject ColonRAII(*this);
1648 /// The map clause modifier token can be either a identifier or the C++
1650 auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
1651 return Tok.isOneOf(tok::identifier, tok::kw_delete);
1654 // The first identifier may be a list item, a map-type or a
1655 // map-type-modifier. The map modifier can also be delete which has the same
1656 // spelling of the C++ delete keyword.
1658 IsMapClauseModifierToken(Tok)
1659 ? static_cast<OpenMPMapClauseKind>(
1660 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1662 Data.DepLinMapLoc = Tok.getLocation();
1663 bool ColonExpected = false;
1665 if (IsMapClauseModifierToken(Tok)) {
1666 if (PP.LookAhead(0).is(tok::colon)) {
1667 if (Data.MapType == OMPC_MAP_unknown)
1668 Diag(Tok, diag::err_omp_unknown_map_type);
1669 else if (Data.MapType == OMPC_MAP_always)
1670 Diag(Tok, diag::err_omp_map_type_missing);
1672 } else if (PP.LookAhead(0).is(tok::comma)) {
1673 if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
1674 PP.LookAhead(2).is(tok::colon)) {
1675 Data.MapTypeModifier = Data.MapType;
1676 if (Data.MapTypeModifier != OMPC_MAP_always) {
1677 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1678 Data.MapTypeModifier = OMPC_MAP_unknown;
1680 MapTypeModifierSpecified = true;
1686 IsMapClauseModifierToken(Tok)
1687 ? static_cast<OpenMPMapClauseKind>(
1688 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1690 if (Data.MapType == OMPC_MAP_unknown ||
1691 Data.MapType == OMPC_MAP_always)
1692 Diag(Tok, diag::err_omp_unknown_map_type);
1695 Data.MapType = OMPC_MAP_tofrom;
1696 Data.IsMapTypeImplicit = true;
1698 } else if (IsMapClauseModifierToken(PP.LookAhead(0))) {
1699 if (PP.LookAhead(1).is(tok::colon)) {
1700 Data.MapTypeModifier = Data.MapType;
1701 if (Data.MapTypeModifier != OMPC_MAP_always) {
1702 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1703 Data.MapTypeModifier = OMPC_MAP_unknown;
1705 MapTypeModifierSpecified = true;
1710 IsMapClauseModifierToken(Tok)
1711 ? static_cast<OpenMPMapClauseKind>(
1712 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1714 if (Data.MapType == OMPC_MAP_unknown ||
1715 Data.MapType == OMPC_MAP_always)
1716 Diag(Tok, diag::err_omp_unknown_map_type);
1719 Data.MapType = OMPC_MAP_tofrom;
1720 Data.IsMapTypeImplicit = true;
1723 Data.MapType = OMPC_MAP_tofrom;
1724 Data.IsMapTypeImplicit = true;
1727 Data.MapType = OMPC_MAP_tofrom;
1728 Data.IsMapTypeImplicit = true;
1731 if (Tok.is(tok::colon))
1732 Data.ColonLoc = ConsumeToken();
1733 else if (ColonExpected)
1734 Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
1737 bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
1738 Kind != OMPC_depend && Kind != OMPC_map) ||
1739 (Kind == OMPC_reduction && !InvalidReductionId) ||
1740 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
1741 (!MapTypeModifierSpecified ||
1742 Data.MapTypeModifier == OMPC_MAP_always)) ||
1743 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
1744 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1745 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
1746 Tok.isNot(tok::annot_pragma_openmp_end))) {
1747 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
1749 ExprResult VarExpr =
1750 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
1751 if (VarExpr.isUsable())
1752 Vars.push_back(VarExpr.get());
1754 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1758 IsComma = Tok.is(tok::comma);
1761 else if (Tok.isNot(tok::r_paren) &&
1762 Tok.isNot(tok::annot_pragma_openmp_end) &&
1763 (!MayHaveTail || Tok.isNot(tok::colon)))
1764 Diag(Tok, diag::err_omp_expected_punc)
1765 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
1766 : getOpenMPClauseName(Kind))
1767 << (Kind == OMPC_flush);
1770 // Parse ')' for linear clause with modifier.
1771 if (NeedRParenForLinear)
1772 LinearT.consumeClose();
1774 // Parse ':' linear-step (or ':' alignment).
1775 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
1777 Data.ColonLoc = Tok.getLocation();
1778 SourceLocation ELoc = ConsumeToken();
1779 ExprResult Tail = ParseAssignmentExpression();
1780 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
1781 if (Tail.isUsable())
1782 Data.TailExpr = Tail.get();
1784 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1790 if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
1792 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1793 (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
1798 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
1799 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'.
1802 /// 'private' '(' list ')'
1803 /// firstprivate-clause:
1804 /// 'firstprivate' '(' list ')'
1805 /// lastprivate-clause:
1806 /// 'lastprivate' '(' list ')'
1808 /// 'shared' '(' list ')'
1810 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
1812 /// 'aligned' '(' list [ ':' alignment ] ')'
1813 /// reduction-clause:
1814 /// 'reduction' '(' reduction-identifier ':' list ')'
1815 /// task_reduction-clause:
1816 /// 'task_reduction' '(' reduction-identifier ':' list ')'
1817 /// copyprivate-clause:
1818 /// 'copyprivate' '(' list ')'
1820 /// 'flush' '(' list ')'
1822 /// 'depend' '(' in | out | inout : list | source ')'
1824 /// 'map' '(' [ [ always , ]
1825 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
1827 /// 'to' '(' list ')'
1829 /// 'from' '(' list ')'
1830 /// use_device_ptr-clause:
1831 /// 'use_device_ptr' '(' list ')'
1832 /// is_device_ptr-clause:
1833 /// 'is_device_ptr' '(' list ')'
1835 /// For 'linear' clause linear-list may have the following forms:
1838 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
1839 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
1840 OpenMPClauseKind Kind) {
1841 SourceLocation Loc = Tok.getLocation();
1842 SourceLocation LOpen = ConsumeToken();
1843 SmallVector<Expr *, 4> Vars;
1844 OpenMPVarListDataTy Data;
1846 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
1849 return Actions.ActOnOpenMPVarListClause(
1850 Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
1851 Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1852 Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,