1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 /// This file implements parsing of all OpenMP directives and clauses.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/StmtOpenMP.h"
15 #include "clang/Basic/OpenMPKinds.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "clang/Basic/TokenKinds.h"
18 #include "clang/Parse/ParseDiagnostic.h"
19 #include "clang/Parse/Parser.h"
20 #include "clang/Parse/RAIIObjectsForParser.h"
21 #include "clang/Sema/Scope.h"
22 #include "llvm/ADT/PointerIntPair.h"
23 #include "llvm/ADT/UniqueVector.h"
24 #include "llvm/Frontend/OpenMP/OMPContext.h"
26 using namespace clang;
27 using namespace llvm::omp;
29 //===----------------------------------------------------------------------===//
30 // OpenMP declarative directives.
31 //===----------------------------------------------------------------------===//
34 enum OpenMPDirectiveKindEx {
35 OMPD_cancellation = unsigned(OMPD_unknown) + 1,
47 OMPD_distribute_parallel,
48 OMPD_teams_distribute_parallel,
49 OMPD_target_teams_distribute_parallel,
56 // Helper to unify the enum class OpenMPDirectiveKind with its extension
57 // the OpenMPDirectiveKindEx enum which allows to use them together as if they
58 // are unsigned values.
59 struct OpenMPDirectiveKindExWrapper {
60 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
61 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
62 bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
63 bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
64 bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
65 operator unsigned() const { return Value; }
66 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
70 class DeclDirectiveListParserHelper final {
71 SmallVector<Expr *, 4> Identifiers;
73 OpenMPDirectiveKind Kind;
76 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
78 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
79 ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
80 P->getCurScope(), SS, NameInfo, Kind);
82 Identifiers.push_back(Res.get());
84 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
88 // Map token string to extended OMP token kind that are
89 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
90 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
91 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
92 if (DKind != OMPD_unknown)
95 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
96 .Case("cancellation", OMPD_cancellation)
97 .Case("data", OMPD_data)
98 .Case("declare", OMPD_declare)
99 .Case("end", OMPD_end)
100 .Case("enter", OMPD_enter)
101 .Case("exit", OMPD_exit)
102 .Case("point", OMPD_point)
103 .Case("reduction", OMPD_reduction)
104 .Case("update", OMPD_update)
105 .Case("mapper", OMPD_mapper)
106 .Case("variant", OMPD_variant)
107 .Case("begin", OMPD_begin)
108 .Default(OMPD_unknown);
111 static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
112 // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
113 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
114 // TODO: add other combined directives in topological order.
115 static const OpenMPDirectiveKindExWrapper F[][3] = {
116 {OMPD_begin, OMPD_declare, OMPD_begin_declare},
117 {OMPD_end, OMPD_declare, OMPD_end_declare},
118 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
119 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
120 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
121 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
122 {OMPD_declare, OMPD_target, OMPD_declare_target},
123 {OMPD_declare, OMPD_variant, OMPD_declare_variant},
124 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
125 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
126 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
127 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
128 {OMPD_distribute_parallel_for, OMPD_simd,
129 OMPD_distribute_parallel_for_simd},
130 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
131 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
132 {OMPD_target, OMPD_data, OMPD_target_data},
133 {OMPD_target, OMPD_enter, OMPD_target_enter},
134 {OMPD_target, OMPD_exit, OMPD_target_exit},
135 {OMPD_target, OMPD_update, OMPD_target_update},
136 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
137 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
138 {OMPD_for, OMPD_simd, OMPD_for_simd},
139 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
140 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
141 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
142 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
143 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
144 {OMPD_target, OMPD_simd, OMPD_target_simd},
145 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
146 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
147 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
148 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
149 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
150 {OMPD_teams_distribute_parallel, OMPD_for,
151 OMPD_teams_distribute_parallel_for},
152 {OMPD_teams_distribute_parallel_for, OMPD_simd,
153 OMPD_teams_distribute_parallel_for_simd},
154 {OMPD_target, OMPD_teams, OMPD_target_teams},
155 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
156 {OMPD_target_teams_distribute, OMPD_parallel,
157 OMPD_target_teams_distribute_parallel},
158 {OMPD_target_teams_distribute, OMPD_simd,
159 OMPD_target_teams_distribute_simd},
160 {OMPD_target_teams_distribute_parallel, OMPD_for,
161 OMPD_target_teams_distribute_parallel_for},
162 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
163 OMPD_target_teams_distribute_parallel_for_simd},
164 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
165 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
166 {OMPD_parallel, OMPD_master, OMPD_parallel_master},
167 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
168 {OMPD_parallel_master_taskloop, OMPD_simd,
169 OMPD_parallel_master_taskloop_simd}};
170 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
171 Token Tok = P.getCurToken();
172 OpenMPDirectiveKindExWrapper DKind =
174 ? static_cast<unsigned>(OMPD_unknown)
175 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
176 if (DKind == OMPD_unknown)
179 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
180 if (DKind != F[I][0])
183 Tok = P.getPreprocessor().LookAhead(0);
184 OpenMPDirectiveKindExWrapper SDKind =
186 ? static_cast<unsigned>(OMPD_unknown)
187 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
188 if (SDKind == OMPD_unknown)
191 if (SDKind == F[I][1]) {
196 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
200 static DeclarationName parseOpenMPReductionId(Parser &P) {
201 Token Tok = P.getCurToken();
202 Sema &Actions = P.getActions();
203 OverloadedOperatorKind OOK = OO_None;
204 // Allow to use 'operator' keyword for C++ operators
205 bool WithOperator = false;
206 if (Tok.is(tok::kw_operator)) {
208 Tok = P.getCurToken();
211 switch (Tok.getKind()) {
212 case tok::plus: // '+'
215 case tok::minus: // '-'
218 case tok::star: // '*'
221 case tok::amp: // '&'
224 case tok::pipe: // '|'
227 case tok::caret: // '^'
230 case tok::ampamp: // '&&'
233 case tok::pipepipe: // '||'
236 case tok::identifier: // identifier
241 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
242 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
243 Parser::StopBeforeMatch);
244 return DeclarationName();
247 auto &DeclNames = Actions.getASTContext().DeclarationNames;
248 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
249 : DeclNames.getCXXOperatorName(OOK);
252 /// Parse 'omp declare reduction' construct.
254 /// declare-reduction-directive:
255 /// annot_pragma_openmp 'declare' 'reduction'
256 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
257 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
258 /// annot_pragma_openmp_end
259 /// <reduction_id> is either a base language identifier or one of the following
260 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
262 Parser::DeclGroupPtrTy
263 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
265 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
266 if (T.expectAndConsume(
267 diag::err_expected_lparen_after,
268 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
269 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
270 return DeclGroupPtrTy();
273 DeclarationName Name = parseOpenMPReductionId(*this);
274 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
275 return DeclGroupPtrTy();
278 bool IsCorrect = !ExpectAndConsume(tok::colon);
280 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
281 return DeclGroupPtrTy();
283 IsCorrect = IsCorrect && !Name.isEmpty();
285 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
286 Diag(Tok.getLocation(), diag::err_expected_type);
290 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
291 return DeclGroupPtrTy();
293 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
294 // Parse list of types until ':' token.
296 ColonProtectionRAIIObject ColonRAII(*this);
299 ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
301 QualType ReductionType =
302 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
303 if (!ReductionType.isNull()) {
304 ReductionTypes.push_back(
305 std::make_pair(ReductionType, Range.getBegin()));
308 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
312 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
316 if (ExpectAndConsume(tok::comma)) {
318 if (Tok.is(tok::annot_pragma_openmp_end)) {
319 Diag(Tok.getLocation(), diag::err_expected_type);
320 return DeclGroupPtrTy();
323 } while (Tok.isNot(tok::annot_pragma_openmp_end));
325 if (ReductionTypes.empty()) {
326 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
327 return DeclGroupPtrTy();
330 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
331 return DeclGroupPtrTy();
334 if (ExpectAndConsume(tok::colon))
337 if (Tok.is(tok::annot_pragma_openmp_end)) {
338 Diag(Tok.getLocation(), diag::err_expected_expression);
339 return DeclGroupPtrTy();
342 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
343 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
345 // Parse <combiner> expression and then parse initializer if any for each
347 unsigned I = 0, E = ReductionTypes.size();
348 for (Decl *D : DRD.get()) {
349 TentativeParsingAction TPA(*this);
350 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
351 Scope::CompoundStmtScope |
352 Scope::OpenMPDirectiveScope);
353 // Parse <combiner> expression.
354 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
355 ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
356 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
357 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
359 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
360 Tok.isNot(tok::annot_pragma_openmp_end)) {
365 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
366 ExprResult InitializerResult;
367 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
368 // Parse <initializer> expression.
369 if (Tok.is(tok::identifier) &&
370 Tok.getIdentifierInfo()->isStr("initializer")) {
373 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
379 BalancedDelimiterTracker T(*this, tok::l_paren,
380 tok::annot_pragma_openmp_end);
382 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
384 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
385 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
386 Scope::CompoundStmtScope |
387 Scope::OpenMPDirectiveScope);
389 VarDecl *OmpPrivParm =
390 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
392 // Check if initializer is omp_priv <init_expr> or something else.
393 if (Tok.is(tok::identifier) &&
394 Tok.getIdentifierInfo()->isStr("omp_priv")) {
396 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
398 InitializerResult = Actions.ActOnFinishFullExpr(
399 ParseAssignmentExpression().get(), D->getLocation(),
400 /*DiscardedValue*/ false);
402 Actions.ActOnOpenMPDeclareReductionInitializerEnd(
403 D, InitializerResult.get(), OmpPrivParm);
404 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
405 Tok.isNot(tok::annot_pragma_openmp_end)) {
411 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
416 // Revert parsing if not the last type, otherwise accept it, we're done with
423 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
427 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
428 // Parse declarator '=' initializer.
429 // If a '==' or '+=' is found, suggest a fixit to '='.
430 if (isTokenEqualOrEqualTypo()) {
433 if (Tok.is(tok::code_completion)) {
434 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
435 Actions.FinalizeDeclaration(OmpPrivParm);
440 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
441 ExprResult Init = ParseInitializer();
443 if (Init.isInvalid()) {
444 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
445 Actions.ActOnInitializerError(OmpPrivParm);
447 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
448 /*DirectInit=*/false);
450 } else if (Tok.is(tok::l_paren)) {
451 // Parse C++ direct initializer: '(' expression-list ')'
452 BalancedDelimiterTracker T(*this, tok::l_paren);
456 CommaLocsTy CommaLocs;
458 SourceLocation LParLoc = T.getOpenLocation();
459 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
460 QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
461 getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
462 OmpPrivParm->getLocation(), Exprs, LParLoc);
463 CalledSignatureHelp = true;
464 return PreferredType;
466 if (ParseExpressionList(Exprs, CommaLocs, [&] {
467 PreferredType.enterFunctionArgument(Tok.getLocation(),
470 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
472 Actions.ActOnInitializerError(OmpPrivParm);
473 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
476 SourceLocation RLoc = Tok.getLocation();
477 if (!T.consumeClose())
478 RLoc = T.getCloseLocation();
480 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
481 "Unexpected number of commas!");
483 ExprResult Initializer =
484 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
485 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
486 /*DirectInit=*/true);
488 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
489 // Parse C++0x braced-init-list.
490 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
492 ExprResult Init(ParseBraceInitializer());
494 if (Init.isInvalid()) {
495 Actions.ActOnInitializerError(OmpPrivParm);
497 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
498 /*DirectInit=*/true);
501 Actions.ActOnUninitializedDecl(OmpPrivParm);
505 /// Parses 'omp declare mapper' directive.
507 /// declare-mapper-directive:
508 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
509 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
510 /// annot_pragma_openmp_end
511 /// <mapper-identifier> and <var> are base language identifiers.
513 Parser::DeclGroupPtrTy
514 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
515 bool IsCorrect = true;
517 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
518 if (T.expectAndConsume(diag::err_expected_lparen_after,
519 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
520 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
521 return DeclGroupPtrTy();
524 // Parse <mapper-identifier>
525 auto &DeclNames = Actions.getASTContext().DeclarationNames;
526 DeclarationName MapperId;
527 if (PP.LookAhead(0).is(tok::colon)) {
528 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
529 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
532 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
536 ExpectAndConsume(tok::colon);
538 // If no mapper identifier is provided, its name is "default" by default
540 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
543 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
544 return DeclGroupPtrTy();
546 // Parse <type> <var>
547 DeclarationName VName;
550 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
551 if (ParsedType.isUsable())
553 Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
554 if (MapperType.isNull())
557 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
558 return DeclGroupPtrTy();
562 IsCorrect &= !T.consumeClose();
564 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
565 return DeclGroupPtrTy();
569 OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
570 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
571 Range.getBegin(), VName, AS);
572 DeclarationNameInfo DirName;
573 SourceLocation Loc = Tok.getLocation();
574 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
575 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
576 ParseScope OMPDirectiveScope(this, ScopeFlags);
577 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
579 // Add the mapper variable declaration.
580 Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
581 DMD, getCurScope(), MapperType, Range.getBegin(), VName);
583 // Parse map clauses.
584 SmallVector<OMPClause *, 6> Clauses;
585 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
586 OpenMPClauseKind CKind = Tok.isAnnotation()
588 : getOpenMPClauseKind(PP.getSpelling(Tok));
589 Actions.StartOpenMPClause(CKind);
591 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
593 Clauses.push_back(Clause);
597 if (Tok.is(tok::comma))
599 Actions.EndOpenMPClause();
601 if (Clauses.empty()) {
602 Diag(Tok, diag::err_omp_expected_clause)
603 << getOpenMPDirectiveName(OMPD_declare_mapper);
608 Actions.EndOpenMPDSABlock(nullptr);
609 OMPDirectiveScope.Exit();
612 Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
614 return DeclGroupPtrTy();
618 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
619 DeclarationName &Name,
620 AccessSpecifier AS) {
621 // Parse the common declaration-specifiers piece.
622 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
623 DeclSpec DS(AttrFactory);
624 ParseSpecifierQualifierList(DS, AS, DSC);
626 // Parse the declarator.
627 DeclaratorContext Context = DeclaratorContext::PrototypeContext;
628 Declarator DeclaratorInfo(DS, Context);
629 ParseDeclarator(DeclaratorInfo);
630 Range = DeclaratorInfo.getSourceRange();
631 if (DeclaratorInfo.getIdentifier() == nullptr) {
632 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
635 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
637 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
641 /// RAII that recreates function context for correct parsing of clauses of
642 /// 'declare simd' construct.
643 /// OpenMP, 2.8.2 declare simd Construct
644 /// The expressions appearing in the clauses of this directive are evaluated in
645 /// the scope of the arguments of the function declaration or definition.
646 class FNContextRAII final {
648 Sema::CXXThisScopeRAII *ThisScope;
649 Parser::ParseScope *TempScope;
650 Parser::ParseScope *FnScope;
651 bool HasTemplateScope = false;
652 bool HasFunScope = false;
653 FNContextRAII() = delete;
654 FNContextRAII(const FNContextRAII &) = delete;
655 FNContextRAII &operator=(const FNContextRAII &) = delete;
658 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
659 Decl *D = *Ptr.get().begin();
660 NamedDecl *ND = dyn_cast<NamedDecl>(D);
661 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
662 Sema &Actions = P.getActions();
664 // Allow 'this' within late-parsed attributes.
665 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
666 ND && ND->isCXXInstanceMember());
668 // If the Decl is templatized, add template parameters to scope.
669 HasTemplateScope = D->isTemplateDecl();
671 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
672 if (HasTemplateScope)
673 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
675 // If the Decl is on a function, add function parameters to the scope.
676 HasFunScope = D->isFunctionOrFunctionTemplate();
677 FnScope = new Parser::ParseScope(
678 &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
681 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
685 P.getActions().ActOnExitFunctionContext();
686 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
688 if (HasTemplateScope)
697 /// Parses clauses for 'declare simd' directive.
699 /// 'inbranch' | 'notinbranch'
700 /// 'simdlen' '(' <expr> ')'
701 /// { 'uniform' '(' <argument_list> ')' }
702 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
703 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
704 static bool parseDeclareSimdClauses(
705 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
706 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
707 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
708 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
710 const Token &Tok = P.getCurToken();
711 bool IsError = false;
712 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
713 if (Tok.isNot(tok::identifier))
715 OMPDeclareSimdDeclAttr::BranchStateTy Out;
716 IdentifierInfo *II = Tok.getIdentifierInfo();
717 StringRef ClauseName = II->getName();
718 // Parse 'inranch|notinbranch' clauses.
719 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
720 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
721 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
723 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
727 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
729 } else if (ClauseName.equals("simdlen")) {
730 if (SimdLen.isUsable()) {
731 P.Diag(Tok, diag::err_omp_more_one_clause)
732 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
737 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
738 if (SimdLen.isInvalid())
741 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
742 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
743 CKind == OMPC_linear) {
744 Parser::OpenMPVarListDataTy Data;
745 SmallVectorImpl<Expr *> *Vars = &Uniforms;
746 if (CKind == OMPC_aligned) {
748 } else if (CKind == OMPC_linear) {
749 Data.ExtraModifier = OMPC_LINEAR_val;
754 if (P.ParseOpenMPVarList(OMPD_declare_simd,
755 getOpenMPClauseKind(ClauseName), *Vars, Data))
757 if (CKind == OMPC_aligned) {
758 Alignments.append(Aligneds.size() - Alignments.size(),
759 Data.DepModOrTailExpr);
760 } else if (CKind == OMPC_linear) {
761 assert(0 <= Data.ExtraModifier &&
762 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
763 "Unexpected linear modifier.");
764 if (P.getActions().CheckOpenMPLinearModifier(
765 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
766 Data.ExtraModifierLoc))
767 Data.ExtraModifier = OMPC_LINEAR_val;
768 LinModifiers.append(Linears.size() - LinModifiers.size(),
770 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
773 // TODO: add parsing of other clauses.
777 if (Tok.is(tok::comma))
783 /// Parse clauses for '#pragma omp declare simd'.
784 Parser::DeclGroupPtrTy
785 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
786 CachedTokens &Toks, SourceLocation Loc) {
787 PP.EnterToken(Tok, /*IsReinject*/ true);
788 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
789 /*IsReinject*/ true);
790 // Consume the previously pushed token.
791 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
792 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
794 FNContextRAII FnContext(*this, Ptr);
795 OMPDeclareSimdDeclAttr::BranchStateTy BS =
796 OMPDeclareSimdDeclAttr::BS_Undefined;
798 SmallVector<Expr *, 4> Uniforms;
799 SmallVector<Expr *, 4> Aligneds;
800 SmallVector<Expr *, 4> Alignments;
801 SmallVector<Expr *, 4> Linears;
802 SmallVector<unsigned, 4> LinModifiers;
803 SmallVector<Expr *, 4> Steps;
805 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
806 Alignments, Linears, LinModifiers, Steps);
807 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
808 // Skip the last annot_pragma_openmp_end.
809 SourceLocation EndLoc = ConsumeAnnotationToken();
812 return Actions.ActOnOpenMPDeclareSimdDirective(
813 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
814 LinModifiers, Steps, SourceRange(Loc, EndLoc));
818 /// Constant used in the diagnostics to distinguish the levels in an OpenMP
819 /// contexts: selector-set={selector(trait, ...), ...}, ....
821 CONTEXT_SELECTOR_SET_LVL = 0,
822 CONTEXT_SELECTOR_LVL = 1,
823 CONTEXT_TRAIT_LVL = 2,
826 static StringRef stringLiteralParser(Parser &P) {
827 ExprResult Res = P.ParseStringLiteralExpression(true);
828 return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
831 static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
833 if (Tok.is(tok::identifier)) {
834 llvm::SmallString<16> Buffer;
835 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
836 (void)P.ConsumeToken();
840 if (tok::isStringLiteral(Tok.getKind()))
841 return stringLiteralParser(P);
843 P.Diag(Tok.getLocation(),
844 diag::warn_omp_declare_variant_string_literal_or_identifier)
849 static bool checkForDuplicates(Parser &P, StringRef Name,
850 SourceLocation NameLoc,
851 llvm::StringMap<SourceLocation> &Seen,
853 auto Res = Seen.try_emplace(Name, NameLoc);
857 // Each trait-set-selector-name, trait-selector-name and trait-name can
858 // only be specified once.
859 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
861 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
867 void Parser::parseOMPTraitPropertyKind(
868 OMPTraitInfo::OMPTraitProperty &TIProperty, llvm::omp::TraitSet Set,
869 llvm::omp::TraitSelector Selector, llvm::StringMap<SourceLocation> &Seen) {
870 TIProperty.Kind = TraitProperty::invalid;
872 SourceLocation NameLoc = Tok.getLocation();
874 getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
876 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
877 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
881 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Name);
882 if (TIProperty.Kind != TraitProperty::invalid) {
883 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
884 TIProperty.Kind = TraitProperty::invalid;
888 // It follows diagnosis and helping notes.
889 // FIXME: We should move the diagnosis string generation into libFrontend.
890 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
891 << Name << getOpenMPContextTraitSelectorName(Selector)
892 << getOpenMPContextTraitSetName(Set);
894 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
895 if (SetForName != TraitSet::invalid) {
896 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
897 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
898 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
899 << Name << "<selector-name>"
900 << "(<property-name>)";
903 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
904 if (SelectorForName != TraitSelector::invalid) {
905 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
906 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
907 bool AllowsTraitScore = false;
908 bool RequiresProperty = false;
909 isValidTraitSelectorForTraitSet(
910 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
911 AllowsTraitScore, RequiresProperty);
912 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
913 << getOpenMPContextTraitSetName(
914 getOpenMPContextTraitSetForSelector(SelectorForName))
915 << Name << (RequiresProperty ? "(<property-name>)" : "");
918 for (const auto &PotentialSet :
919 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
921 TraitProperty PropertyForName =
922 getOpenMPContextTraitPropertyKind(PotentialSet, Name);
923 if (PropertyForName == TraitProperty::invalid)
925 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
926 << getOpenMPContextTraitSetName(
927 getOpenMPContextTraitSetForProperty(PropertyForName))
928 << getOpenMPContextTraitSelectorName(
929 getOpenMPContextTraitSelectorForProperty(PropertyForName))
930 << ("(" + Name + ")").str();
933 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
934 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
937 void Parser::parseOMPContextProperty(OMPTraitInfo::OMPTraitSelector &TISelector,
938 llvm::omp::TraitSet Set,
939 llvm::StringMap<SourceLocation> &Seen) {
940 assert(TISelector.Kind != TraitSelector::user_condition &&
941 "User conditions are special properties not handled here!");
943 SourceLocation PropertyLoc = Tok.getLocation();
944 OMPTraitInfo::OMPTraitProperty TIProperty;
945 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
947 // If we have an invalid property here we already issued a warning.
948 if (TIProperty.Kind == TraitProperty::invalid) {
949 if (PropertyLoc != Tok.getLocation())
950 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
951 << CONTEXT_TRAIT_LVL;
955 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
956 TISelector.Kind, Set)) {
957 // If we make it here the property, selector, set, score, condition, ... are
958 // all valid (or have been corrected). Thus we can record the property.
959 TISelector.Properties.push_back(TIProperty);
963 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
964 << getOpenMPContextTraitPropertyName(TIProperty.Kind)
965 << getOpenMPContextTraitSelectorName(TISelector.Kind)
966 << getOpenMPContextTraitSetName(Set);
967 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
968 << getOpenMPContextTraitPropertyName(TIProperty.Kind)
969 << getOpenMPContextTraitSelectorName(
970 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
971 << getOpenMPContextTraitSetName(
972 getOpenMPContextTraitSetForProperty(TIProperty.Kind));
973 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
974 << CONTEXT_TRAIT_LVL;
977 void Parser::parseOMPTraitSelectorKind(
978 OMPTraitInfo::OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
979 llvm::StringMap<SourceLocation> &Seen) {
980 TISelector.Kind = TraitSelector::invalid;
982 SourceLocation NameLoc = Tok.getLocation();
983 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL
986 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
987 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
991 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name);
992 if (TISelector.Kind != TraitSelector::invalid) {
993 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
994 TISelector.Kind = TraitSelector::invalid;
998 // It follows diagnosis and helping notes.
999 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1000 << Name << getOpenMPContextTraitSetName(Set);
1002 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1003 if (SetForName != TraitSet::invalid) {
1004 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1005 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1006 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1007 << Name << "<selector-name>"
1008 << "<property-name>";
1011 for (const auto &PotentialSet :
1012 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1013 TraitSet::device}) {
1014 TraitProperty PropertyForName =
1015 getOpenMPContextTraitPropertyKind(PotentialSet, Name);
1016 if (PropertyForName == TraitProperty::invalid)
1018 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1019 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1020 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1021 << getOpenMPContextTraitSetName(
1022 getOpenMPContextTraitSetForProperty(PropertyForName))
1023 << getOpenMPContextTraitSelectorName(
1024 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1025 << ("(" + Name + ")").str();
1028 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1029 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1032 /// Parse optional 'score' '(' <expr> ')' ':'.
1033 static ExprResult parseContextScore(Parser &P) {
1034 ExprResult ScoreExpr;
1035 llvm::SmallString<16> Buffer;
1036 StringRef SelectorName =
1037 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1038 if (!SelectorName.equals("score"))
1040 (void)P.ConsumeToken();
1041 SourceLocation RLoc;
1042 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
1044 if (P.getCurToken().is(tok::colon))
1045 (void)P.ConsumeAnyToken();
1047 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
1049 << "score expression";
1053 /// Parses an OpenMP context selector.
1055 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
1056 void Parser::parseOMPContextSelector(
1057 OMPTraitInfo::OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
1058 llvm::StringMap<SourceLocation> &SeenSelectors) {
1059 unsigned short OuterPC = ParenCount;
1061 // If anything went wrong we issue an error or warning and then skip the rest
1062 // of the selector. However, commas are ambiguous so we look for the nesting
1063 // of parentheses here as well.
1064 auto FinishSelector = [OuterPC, this]() -> void {
1067 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1068 tok::annot_pragma_openmp_end},
1071 if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
1072 (void)ConsumeParen();
1073 if (OuterPC <= ParenCount) {
1077 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
1081 (void)ConsumeAnyToken();
1083 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1084 << CONTEXT_SELECTOR_LVL;
1087 SourceLocation SelectorLoc = Tok.getLocation();
1088 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1089 if (TISelector.Kind == TraitSelector::invalid)
1090 return FinishSelector();
1092 bool AllowsTraitScore = false;
1093 bool RequiresProperty = false;
1094 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
1095 RequiresProperty)) {
1096 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1097 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1098 << getOpenMPContextTraitSetName(Set);
1099 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1100 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1101 << getOpenMPContextTraitSetName(
1102 getOpenMPContextTraitSetForSelector(TISelector.Kind))
1103 << RequiresProperty;
1104 return FinishSelector();
1107 if (!RequiresProperty) {
1108 TISelector.Properties.push_back(
1109 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind)});
1113 if (!Tok.is(tok::l_paren)) {
1114 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1115 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1116 << getOpenMPContextTraitSetName(Set);
1117 return FinishSelector();
1120 if (TISelector.Kind == TraitSelector::user_condition) {
1121 SourceLocation RLoc;
1122 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
1123 if (!Condition.isUsable())
1124 return FinishSelector();
1125 TISelector.ScoreOrCondition = Condition.get();
1126 TISelector.Properties.push_back({TraitProperty::user_condition_unknown});
1130 BalancedDelimiterTracker BDT(*this, tok::l_paren,
1131 tok::annot_pragma_openmp_end);
1133 (void)BDT.consumeOpen();
1135 SourceLocation ScoreLoc = Tok.getLocation();
1136 ExprResult Score = parseContextScore(*this);
1138 if (!AllowsTraitScore && !Score.isUnset()) {
1139 if (Score.isUsable()) {
1140 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1141 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1142 << getOpenMPContextTraitSetName(Set) << Score.get();
1144 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1145 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1146 << getOpenMPContextTraitSetName(Set) << "<invalid>";
1148 Score = ExprResult();
1151 if (Score.isUsable())
1152 TISelector.ScoreOrCondition = Score.get();
1154 llvm::StringMap<SourceLocation> SeenProperties;
1156 parseOMPContextProperty(TISelector, Set, SeenProperties);
1157 } while (TryConsumeToken(tok::comma));
1163 void Parser::parseOMPTraitSetKind(OMPTraitInfo::OMPTraitSet &TISet,
1164 llvm::StringMap<SourceLocation> &Seen) {
1165 TISet.Kind = TraitSet::invalid;
1167 SourceLocation NameLoc = Tok.getLocation();
1168 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL
1171 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1172 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1176 TISet.Kind = getOpenMPContextTraitSetKind(Name);
1177 if (TISet.Kind != TraitSet::invalid) {
1178 if (checkForDuplicates(*this, Name, NameLoc, Seen,
1179 CONTEXT_SELECTOR_SET_LVL))
1180 TISet.Kind = TraitSet::invalid;
1184 // It follows diagnosis and helping notes.
1185 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1187 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1188 if (SelectorForName != TraitSelector::invalid) {
1189 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1190 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1191 bool AllowsTraitScore = false;
1192 bool RequiresProperty = false;
1193 isValidTraitSelectorForTraitSet(
1194 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1195 AllowsTraitScore, RequiresProperty);
1196 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1197 << getOpenMPContextTraitSetName(
1198 getOpenMPContextTraitSetForSelector(SelectorForName))
1199 << Name << (RequiresProperty ? "(<property-name>)" : "");
1202 for (const auto &PotentialSet :
1203 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1204 TraitSet::device}) {
1205 TraitProperty PropertyForName =
1206 getOpenMPContextTraitPropertyKind(PotentialSet, Name);
1207 if (PropertyForName == TraitProperty::invalid)
1209 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1210 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1211 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1212 << getOpenMPContextTraitSetName(
1213 getOpenMPContextTraitSetForProperty(PropertyForName))
1214 << getOpenMPContextTraitSelectorName(
1215 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1216 << ("(" + Name + ")").str();
1219 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1220 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1223 /// Parses an OpenMP context selector set.
1225 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
1226 void Parser::parseOMPContextSelectorSet(
1227 OMPTraitInfo::OMPTraitSet &TISet,
1228 llvm::StringMap<SourceLocation> &SeenSets) {
1229 auto OuterBC = BraceCount;
1231 // If anything went wrong we issue an error or warning and then skip the rest
1232 // of the set. However, commas are ambiguous so we look for the nesting
1233 // of braces here as well.
1234 auto FinishSelectorSet = [this, OuterBC]() -> void {
1237 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1238 tok::annot_pragma_openmp_end},
1241 if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
1242 (void)ConsumeBrace();
1243 if (OuterBC <= BraceCount) {
1247 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
1251 (void)ConsumeAnyToken();
1253 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1254 << CONTEXT_SELECTOR_SET_LVL;
1257 parseOMPTraitSetKind(TISet, SeenSets);
1258 if (TISet.Kind == TraitSet::invalid)
1259 return FinishSelectorSet();
1262 if (!TryConsumeToken(tok::equal))
1263 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1265 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
1270 if (Tok.is(tok::l_brace)) {
1271 (void)ConsumeBrace();
1273 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1275 << ("'=' that follows the context set name \"" +
1276 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1280 llvm::StringMap<SourceLocation> SeenSelectors;
1282 OMPTraitInfo::OMPTraitSelector TISelector;
1283 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1284 if (TISelector.Kind != TraitSelector::invalid &&
1285 !TISelector.Properties.empty())
1286 TISet.Selectors.push_back(TISelector);
1287 } while (TryConsumeToken(tok::comma));
1290 if (Tok.is(tok::r_brace)) {
1291 (void)ConsumeBrace();
1293 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1295 << ("context selectors for the context set \"" +
1296 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1301 /// Parse OpenMP context selectors:
1303 /// <trait-set-selector> [, <trait-set-selector>]*
1304 bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1305 llvm::StringMap<SourceLocation> SeenSets;
1307 OMPTraitInfo::OMPTraitSet TISet;
1308 parseOMPContextSelectorSet(TISet, SeenSets);
1309 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1310 TI.Sets.push_back(TISet);
1311 } while (TryConsumeToken(tok::comma));
1316 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
1317 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1319 SourceLocation Loc) {
1320 PP.EnterToken(Tok, /*IsReinject*/ true);
1321 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1322 /*IsReinject*/ true);
1323 // Consume the previously pushed token.
1324 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1325 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1327 FNContextRAII FnContext(*this, Ptr);
1328 // Parse function declaration id.
1329 SourceLocation RLoc;
1330 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1331 // instead of MemberExprs.
1332 ExprResult AssociatedFunction;
1334 // Do not mark function as is used to prevent its emission if this is the
1335 // only place where it is used.
1336 EnterExpressionEvaluationContext Unevaluated(
1337 Actions, Sema::ExpressionEvaluationContext::Unevaluated);
1338 AssociatedFunction = ParseOpenMPParensExpr(
1339 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1340 /*IsAddressOfOperand=*/true);
1342 if (!AssociatedFunction.isUsable()) {
1343 if (!Tok.is(tok::annot_pragma_openmp_end))
1344 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1346 // Skip the last annot_pragma_openmp_end.
1347 (void)ConsumeAnnotationToken();
1351 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
1352 if (parseOMPDeclareVariantMatchClause(Loc, TI))
1355 Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1356 Actions.checkOpenMPDeclareVariantFunction(
1357 Ptr, AssociatedFunction.get(), TI,
1358 SourceRange(Loc, Tok.getLocation()));
1360 // Skip last tokens.
1361 while (Tok.isNot(tok::annot_pragma_openmp_end))
1363 if (DeclVarData && !TI.Sets.empty())
1364 Actions.ActOnOpenMPDeclareVariantDirective(
1365 DeclVarData->first, DeclVarData->second, TI,
1366 SourceRange(Loc, Tok.getLocation()));
1368 // Skip the last annot_pragma_openmp_end.
1369 (void)ConsumeAnnotationToken();
1372 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1375 OpenMPClauseKind CKind = Tok.isAnnotation()
1377 : getOpenMPClauseKind(PP.getSpelling(Tok));
1378 if (CKind != OMPC_match) {
1379 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1380 << getOpenMPClauseName(OMPC_match);
1381 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
1383 // Skip the last annot_pragma_openmp_end.
1384 (void)ConsumeAnnotationToken();
1387 (void)ConsumeToken();
1389 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1390 if (T.expectAndConsume(diag::err_expected_lparen_after,
1391 getOpenMPClauseName(OMPC_match))) {
1392 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1394 // Skip the last annot_pragma_openmp_end.
1395 (void)ConsumeAnnotationToken();
1399 // Parse inner context selectors.
1400 parseOMPContextSelectors(Loc, TI);
1403 (void)T.consumeClose();
1407 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1410 /// 'default' '(' 'none' | 'shared' ')
1412 /// proc_bind-clause:
1413 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1415 /// device_type-clause:
1416 /// 'device_type' '(' 'host' | 'nohost' | 'any' )'
1418 struct SimpleClauseData {
1421 SourceLocation LOpen;
1422 SourceLocation TypeLoc;
1423 SourceLocation RLoc;
1424 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1425 SourceLocation TypeLoc, SourceLocation RLoc)
1426 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1428 } // anonymous namespace
1430 static Optional<SimpleClauseData>
1431 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
1432 const Token &Tok = P.getCurToken();
1433 SourceLocation Loc = Tok.getLocation();
1434 SourceLocation LOpen = P.ConsumeToken();
1436 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1437 if (T.expectAndConsume(diag::err_expected_lparen_after,
1438 getOpenMPClauseName(Kind)))
1441 unsigned Type = getOpenMPSimpleClauseType(
1442 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok));
1443 SourceLocation TypeLoc = Tok.getLocation();
1444 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1445 Tok.isNot(tok::annot_pragma_openmp_end))
1446 P.ConsumeAnyToken();
1449 SourceLocation RLoc = Tok.getLocation();
1450 if (!T.consumeClose())
1451 RLoc = T.getCloseLocation();
1453 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1456 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
1457 // OpenMP 4.5 syntax with list of entities.
1458 Sema::NamedDeclSetType SameDirectiveDecls;
1459 SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
1463 OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
1464 SourceLocation DeviceTypeLoc;
1465 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1466 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1467 if (Tok.is(tok::identifier)) {
1468 IdentifierInfo *II = Tok.getIdentifierInfo();
1469 StringRef ClauseName = II->getName();
1470 bool IsDeviceTypeClause =
1471 getLangOpts().OpenMP >= 50 &&
1472 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1473 // Parse 'to|link|device_type' clauses.
1474 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
1475 !IsDeviceTypeClause) {
1476 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1477 << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
1480 // Parse 'device_type' clause and go to next clause if any.
1481 if (IsDeviceTypeClause) {
1482 Optional<SimpleClauseData> DevTypeData =
1483 parseOpenMPSimpleClause(*this, OMPC_device_type);
1484 if (DevTypeData.hasValue()) {
1485 if (DeviceTypeLoc.isValid()) {
1486 // We already saw another device_type clause, diagnose it.
1487 Diag(DevTypeData.getValue().Loc,
1488 diag::warn_omp_more_one_device_type_clause);
1490 switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
1491 case OMPC_DEVICE_TYPE_any:
1492 DT = OMPDeclareTargetDeclAttr::DT_Any;
1494 case OMPC_DEVICE_TYPE_host:
1495 DT = OMPDeclareTargetDeclAttr::DT_Host;
1497 case OMPC_DEVICE_TYPE_nohost:
1498 DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1500 case OMPC_DEVICE_TYPE_unknown:
1501 llvm_unreachable("Unexpected device_type");
1503 DeviceTypeLoc = DevTypeData.getValue().Loc;
1509 auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
1510 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
1511 NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
1512 getCurScope(), SS, NameInfo, SameDirectiveDecls);
1514 DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
1516 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1517 /*AllowScopeSpecifier=*/true))
1520 // Consume optional ','.
1521 if (Tok.is(tok::comma))
1524 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1526 for (auto &MTLocDecl : DeclareTargetDecls) {
1527 OMPDeclareTargetDeclAttr::MapTypeTy MT;
1530 std::tie(MT, Loc, ND) = MTLocDecl;
1531 // device_type clause is applied only to functions.
1532 Actions.ActOnOpenMPDeclareTargetName(
1533 ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
1535 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
1536 SameDirectiveDecls.end());
1538 return DeclGroupPtrTy();
1539 return Actions.BuildDeclaratorGroup(Decls);
1542 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1543 // The last seen token is annot_pragma_openmp_end - need to check for
1545 if (Tok.is(tok::annot_pragma_openmp_end))
1548 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1549 << getOpenMPDirectiveName(DKind);
1550 while (Tok.isNot(tok::annot_pragma_openmp_end))
1554 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1555 OpenMPDirectiveKind ExpectedKind,
1556 OpenMPDirectiveKind FoundKind,
1557 SourceLocation BeginLoc,
1558 SourceLocation FoundLoc,
1559 bool SkipUntilOpenMPEnd) {
1560 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1562 if (FoundKind == ExpectedKind) {
1564 skipUntilPragmaOpenMPEnd(ExpectedKind);
1568 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1570 Diag(BeginLoc, diag::note_matching)
1571 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
1572 if (SkipUntilOpenMPEnd)
1573 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1576 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
1577 SourceLocation DKLoc) {
1578 parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind,
1579 DKLoc, Tok.getLocation(),
1580 /* SkipUntilOpenMPEnd */ false);
1581 // Skip the last annot_pragma_openmp_end.
1582 if (Tok.is(tok::annot_pragma_openmp_end))
1583 ConsumeAnnotationToken();
1586 /// Parsing of declarative OpenMP directives.
1588 /// threadprivate-directive:
1589 /// annot_pragma_openmp 'threadprivate' simple-variable-list
1590 /// annot_pragma_openmp_end
1592 /// allocate-directive:
1593 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
1594 /// annot_pragma_openmp_end
1596 /// declare-reduction-directive:
1597 /// annot_pragma_openmp 'declare' 'reduction' [...]
1598 /// annot_pragma_openmp_end
1600 /// declare-mapper-directive:
1601 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1602 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
1603 /// annot_pragma_openmp_end
1605 /// declare-simd-directive:
1606 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
1607 /// annot_pragma_openmp_end
1608 /// <function declaration/definition>
1610 /// requires directive:
1611 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
1612 /// annot_pragma_openmp_end
1614 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1615 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
1616 DeclSpec::TST TagType, Decl *Tag) {
1617 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1618 ParsingOpenMPDirectiveRAII DirScope(*this);
1619 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1622 OpenMPDirectiveKind DKind;
1624 TentativeParsingAction TPA(*this);
1625 Loc = ConsumeAnnotationToken();
1626 DKind = parseOpenMPDirectiveKind(*this);
1627 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1628 // Need to delay parsing until completion of the parent class.
1632 Toks.push_back(Tok);
1633 while (Cnt && Tok.isNot(tok::eof)) {
1634 (void)ConsumeAnyToken();
1635 if (Tok.is(tok::annot_pragma_openmp))
1637 else if (Tok.is(tok::annot_pragma_openmp_end))
1639 Toks.push_back(Tok);
1641 // Skip last annot_pragma_openmp_end.
1643 (void)ConsumeAnyToken();
1644 auto *LP = new LateParsedPragma(this, AS);
1646 getCurrentClass().LateParsedDeclarations.push_back(LP);
1651 Loc = ConsumeAnnotationToken();
1652 DKind = parseOpenMPDirectiveKind(*this);
1656 case OMPD_threadprivate: {
1658 DeclDirectiveListParserHelper Helper(this, DKind);
1659 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1660 /*AllowScopeSpecifier=*/true)) {
1661 skipUntilPragmaOpenMPEnd(DKind);
1662 // Skip the last annot_pragma_openmp_end.
1663 ConsumeAnnotationToken();
1664 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
1665 Helper.getIdentifiers());
1669 case OMPD_allocate: {
1671 DeclDirectiveListParserHelper Helper(this, DKind);
1672 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1673 /*AllowScopeSpecifier=*/true)) {
1674 SmallVector<OMPClause *, 1> Clauses;
1675 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1676 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1678 FirstClauses(OMPC_unknown + 1);
1679 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1680 OpenMPClauseKind CKind =
1681 Tok.isAnnotation() ? OMPC_unknown
1682 : getOpenMPClauseKind(PP.getSpelling(Tok));
1683 Actions.StartOpenMPClause(CKind);
1684 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1685 !FirstClauses[CKind].getInt());
1686 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1688 FirstClauses[CKind].setInt(true);
1689 if (Clause != nullptr)
1690 Clauses.push_back(Clause);
1691 if (Tok.is(tok::annot_pragma_openmp_end)) {
1692 Actions.EndOpenMPClause();
1696 if (Tok.is(tok::comma))
1698 Actions.EndOpenMPClause();
1700 skipUntilPragmaOpenMPEnd(DKind);
1702 // Skip the last annot_pragma_openmp_end.
1703 ConsumeAnnotationToken();
1704 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
1709 case OMPD_requires: {
1710 SourceLocation StartLoc = ConsumeToken();
1711 SmallVector<OMPClause *, 5> Clauses;
1712 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
1713 FirstClauses(OMPC_unknown + 1);
1714 if (Tok.is(tok::annot_pragma_openmp_end)) {
1715 Diag(Tok, diag::err_omp_expected_clause)
1716 << getOpenMPDirectiveName(OMPD_requires);
1719 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1720 OpenMPClauseKind CKind = Tok.isAnnotation()
1722 : getOpenMPClauseKind(PP.getSpelling(Tok));
1723 Actions.StartOpenMPClause(CKind);
1724 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
1725 !FirstClauses[CKind].getInt());
1726 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1728 FirstClauses[CKind].setInt(true);
1729 if (Clause != nullptr)
1730 Clauses.push_back(Clause);
1731 if (Tok.is(tok::annot_pragma_openmp_end)) {
1732 Actions.EndOpenMPClause();
1736 if (Tok.is(tok::comma))
1738 Actions.EndOpenMPClause();
1740 // Consume final annot_pragma_openmp_end
1741 if (Clauses.empty()) {
1742 Diag(Tok, diag::err_omp_expected_clause)
1743 << getOpenMPDirectiveName(OMPD_requires);
1744 ConsumeAnnotationToken();
1747 ConsumeAnnotationToken();
1748 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
1750 case OMPD_declare_reduction:
1752 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
1753 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
1754 // Skip the last annot_pragma_openmp_end.
1755 ConsumeAnnotationToken();
1759 case OMPD_declare_mapper: {
1761 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1762 // Skip the last annot_pragma_openmp_end.
1763 ConsumeAnnotationToken();
1768 case OMPD_begin_declare_variant: {
1770 // { #pragma omp begin declare variant clause }
1771 // <function-declaration-or-definition-sequence>
1772 // { #pragma omp end declare variant }
1775 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
1776 if (parseOMPDeclareVariantMatchClause(Loc, TI))
1779 // Skip last tokens.
1780 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
1782 VariantMatchInfo VMI;
1783 ASTContext &ASTCtx = Actions.getASTContext();
1784 TI.getAsVariantMatchInfo(ASTCtx, VMI, /* DeviceSetOnly */ true);
1785 OMPContext OMPCtx(ASTCtx.getLangOpts().OpenMPIsDevice,
1786 ASTCtx.getTargetInfo().getTriple());
1788 if (isVariantApplicableInContext(VMI, OMPCtx)) {
1789 Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI);
1793 // Elide all the code till the matching end declare variant was found.
1794 unsigned Nesting = 1;
1795 SourceLocation DKLoc;
1796 OpenMPDirectiveKind DK = OMPD_unknown;
1798 DKLoc = Tok.getLocation();
1799 DK = parseOpenMPDirectiveKind(*this);
1800 if (DK == OMPD_end_declare_variant)
1802 else if (DK == OMPD_begin_declare_variant)
1804 if (!Nesting || isEofOrEom())
1809 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
1810 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
1815 case OMPD_end_declare_variant: {
1816 if (Actions.isInOpenMPDeclareVariantScope())
1817 Actions.ActOnOpenMPEndDeclareVariant();
1819 Diag(Loc, diag::err_expected_begin_declare_variant);
1823 case OMPD_declare_variant:
1824 case OMPD_declare_simd: {
1826 // { #pragma omp declare {simd|variant} }
1827 // <function-declaration-or-definition>
1830 Toks.push_back(Tok);
1832 while(Tok.isNot(tok::annot_pragma_openmp_end)) {
1833 Toks.push_back(Tok);
1836 Toks.push_back(Tok);
1840 if (Tok.is(tok::annot_pragma_openmp)) {
1841 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
1843 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1844 // Here we expect to see some function declaration.
1845 if (AS == AS_none) {
1846 assert(TagType == DeclSpec::TST_unspecified);
1847 MaybeParseCXX11Attributes(Attrs);
1848 ParsingDeclSpec PDS(*this);
1849 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1852 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1856 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
1857 << (DKind == OMPD_declare_simd ? 0 : 1);
1858 return DeclGroupPtrTy();
1860 if (DKind == OMPD_declare_simd)
1861 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1862 assert(DKind == OMPD_declare_variant &&
1863 "Expected declare variant directive only");
1864 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
1867 case OMPD_declare_target: {
1868 SourceLocation DTLoc = ConsumeAnyToken();
1869 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1870 return ParseOMPDeclareTargetClauses();
1873 // Skip the last annot_pragma_openmp_end.
1876 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1877 return DeclGroupPtrTy();
1879 llvm::SmallVector<Decl *, 4> Decls;
1880 DKind = parseOpenMPDirectiveKind(*this);
1881 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1882 Tok.isNot(tok::r_brace)) {
1884 // Here we expect to see some function declaration.
1885 if (AS == AS_none) {
1886 assert(TagType == DeclSpec::TST_unspecified);
1887 MaybeParseCXX11Attributes(Attrs);
1888 ParsingDeclSpec PDS(*this);
1889 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1892 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1895 DeclGroupRef Ref = Ptr.get();
1896 Decls.append(Ref.begin(), Ref.end());
1898 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
1899 TentativeParsingAction TPA(*this);
1900 ConsumeAnnotationToken();
1901 DKind = parseOpenMPDirectiveKind(*this);
1902 if (DKind != OMPD_end_declare_target)
1909 ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1910 Actions.ActOnFinishOpenMPDeclareTargetDirective();
1911 return Actions.BuildDeclaratorGroup(Decls);
1914 Diag(Tok, diag::err_omp_unknown_directive);
1919 case OMPD_taskyield:
1922 case OMPD_taskgroup:
1934 case OMPD_parallel_for:
1935 case OMPD_parallel_for_simd:
1936 case OMPD_parallel_sections:
1937 case OMPD_parallel_master:
1941 case OMPD_cancellation_point:
1943 case OMPD_target_data:
1944 case OMPD_target_enter_data:
1945 case OMPD_target_exit_data:
1946 case OMPD_target_parallel:
1947 case OMPD_target_parallel_for:
1949 case OMPD_taskloop_simd:
1950 case OMPD_master_taskloop:
1951 case OMPD_master_taskloop_simd:
1952 case OMPD_parallel_master_taskloop:
1953 case OMPD_parallel_master_taskloop_simd:
1954 case OMPD_distribute:
1955 case OMPD_end_declare_target:
1956 case OMPD_target_update:
1957 case OMPD_distribute_parallel_for:
1958 case OMPD_distribute_parallel_for_simd:
1959 case OMPD_distribute_simd:
1960 case OMPD_target_parallel_for_simd:
1961 case OMPD_target_simd:
1962 case OMPD_teams_distribute:
1963 case OMPD_teams_distribute_simd:
1964 case OMPD_teams_distribute_parallel_for_simd:
1965 case OMPD_teams_distribute_parallel_for:
1966 case OMPD_target_teams:
1967 case OMPD_target_teams_distribute:
1968 case OMPD_target_teams_distribute_parallel_for:
1969 case OMPD_target_teams_distribute_parallel_for_simd:
1970 case OMPD_target_teams_distribute_simd:
1971 Diag(Tok, diag::err_omp_unexpected_directive)
1972 << 1 << getOpenMPDirectiveName(DKind);
1975 while (Tok.isNot(tok::annot_pragma_openmp_end))
1981 /// Parsing of declarative or executable OpenMP directives.
1983 /// threadprivate-directive:
1984 /// annot_pragma_openmp 'threadprivate' simple-variable-list
1985 /// annot_pragma_openmp_end
1987 /// allocate-directive:
1988 /// annot_pragma_openmp 'allocate' simple-variable-list
1989 /// annot_pragma_openmp_end
1991 /// declare-reduction-directive:
1992 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
1993 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
1994 /// ('omp_priv' '=' <expression>|<function_call>) ')']
1995 /// annot_pragma_openmp_end
1997 /// declare-mapper-directive:
1998 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1999 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
2000 /// annot_pragma_openmp_end
2002 /// executable-directive:
2003 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
2004 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2005 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2006 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
2007 /// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2008 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2009 /// 'master taskloop' | 'master taskloop simd' | 'parallel master
2010 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2011 /// enter data' | 'target exit data' | 'target parallel' | 'target
2012 /// parallel for' | 'target update' | 'distribute parallel for' |
2013 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel
2014 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2015 /// simd' | 'teams distribute parallel for simd' | 'teams distribute
2016 /// parallel for' | 'target teams' | 'target teams distribute' | 'target
2017 /// teams distribute parallel for' | 'target teams distribute parallel
2018 /// for simd' | 'target teams distribute simd' {clause}
2019 /// annot_pragma_openmp_end
2022 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
2023 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
2024 ParsingOpenMPDirectiveRAII DirScope(*this);
2025 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2026 SmallVector<OMPClause *, 5> Clauses;
2027 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
2028 FirstClauses(OMPC_unknown + 1);
2029 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2030 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
2031 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
2032 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
2033 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2034 // Name of critical directive.
2035 DeclarationNameInfo DirName;
2036 StmtResult Directive = StmtError();
2037 bool HasAssociatedStatement = true;
2040 case OMPD_threadprivate: {
2041 // FIXME: Should this be permitted in C++?
2042 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
2043 ParsedStmtContext()) {
2044 Diag(Tok, diag::err_omp_immediate_directive)
2045 << getOpenMPDirectiveName(DKind) << 0;
2048 DeclDirectiveListParserHelper Helper(this, DKind);
2049 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2050 /*AllowScopeSpecifier=*/false)) {
2051 skipUntilPragmaOpenMPEnd(DKind);
2052 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
2053 Loc, Helper.getIdentifiers());
2054 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2056 SkipUntil(tok::annot_pragma_openmp_end);
2059 case OMPD_allocate: {
2060 // FIXME: Should this be permitted in C++?
2061 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
2062 ParsedStmtContext()) {
2063 Diag(Tok, diag::err_omp_immediate_directive)
2064 << getOpenMPDirectiveName(DKind) << 0;
2067 DeclDirectiveListParserHelper Helper(this, DKind);
2068 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2069 /*AllowScopeSpecifier=*/false)) {
2070 SmallVector<OMPClause *, 1> Clauses;
2071 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2072 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
2074 FirstClauses(OMPC_unknown + 1);
2075 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2076 OpenMPClauseKind CKind =
2077 Tok.isAnnotation() ? OMPC_unknown
2078 : getOpenMPClauseKind(PP.getSpelling(Tok));
2079 Actions.StartOpenMPClause(CKind);
2080 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2081 !FirstClauses[CKind].getInt());
2082 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2084 FirstClauses[CKind].setInt(true);
2085 if (Clause != nullptr)
2086 Clauses.push_back(Clause);
2087 if (Tok.is(tok::annot_pragma_openmp_end)) {
2088 Actions.EndOpenMPClause();
2092 if (Tok.is(tok::comma))
2094 Actions.EndOpenMPClause();
2096 skipUntilPragmaOpenMPEnd(DKind);
2098 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
2099 Loc, Helper.getIdentifiers(), Clauses);
2100 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2102 SkipUntil(tok::annot_pragma_openmp_end);
2105 case OMPD_declare_reduction:
2107 if (DeclGroupPtrTy Res =
2108 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2109 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2111 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2113 SkipUntil(tok::annot_pragma_openmp_end);
2116 case OMPD_declare_mapper: {
2118 if (DeclGroupPtrTy Res =
2119 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2120 // Skip the last annot_pragma_openmp_end.
2121 ConsumeAnnotationToken();
2122 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2124 SkipUntil(tok::annot_pragma_openmp_end);
2131 case OMPD_taskyield:
2134 case OMPD_cancellation_point:
2136 case OMPD_target_enter_data:
2137 case OMPD_target_exit_data:
2138 case OMPD_target_update:
2139 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2140 ParsedStmtContext()) {
2141 Diag(Tok, diag::err_omp_immediate_directive)
2142 << getOpenMPDirectiveName(DKind) << 0;
2144 HasAssociatedStatement = false;
2145 // Fall through for further analysis.
2156 case OMPD_parallel_for:
2157 case OMPD_parallel_for_simd:
2158 case OMPD_parallel_sections:
2159 case OMPD_parallel_master:
2165 case OMPD_taskgroup:
2166 case OMPD_target_data:
2167 case OMPD_target_parallel:
2168 case OMPD_target_parallel_for:
2170 case OMPD_taskloop_simd:
2171 case OMPD_master_taskloop:
2172 case OMPD_master_taskloop_simd:
2173 case OMPD_parallel_master_taskloop:
2174 case OMPD_parallel_master_taskloop_simd:
2175 case OMPD_distribute:
2176 case OMPD_distribute_parallel_for:
2177 case OMPD_distribute_parallel_for_simd:
2178 case OMPD_distribute_simd:
2179 case OMPD_target_parallel_for_simd:
2180 case OMPD_target_simd:
2181 case OMPD_teams_distribute:
2182 case OMPD_teams_distribute_simd:
2183 case OMPD_teams_distribute_parallel_for_simd:
2184 case OMPD_teams_distribute_parallel_for:
2185 case OMPD_target_teams:
2186 case OMPD_target_teams_distribute:
2187 case OMPD_target_teams_distribute_parallel_for:
2188 case OMPD_target_teams_distribute_parallel_for_simd:
2189 case OMPD_target_teams_distribute_simd: {
2190 // Special processing for flush and depobj clauses.
2192 bool ImplicitClauseAllowed = false;
2193 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2195 ImplicitClauseAllowed = true;
2198 // Parse directive name of the 'critical' directive if any.
2199 if (DKind == OMPD_critical) {
2200 BalancedDelimiterTracker T(*this, tok::l_paren,
2201 tok::annot_pragma_openmp_end);
2202 if (!T.consumeOpen()) {
2203 if (Tok.isAnyIdentifier()) {
2205 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2208 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2212 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2213 CancelRegion = parseOpenMPDirectiveKind(*this);
2214 if (Tok.isNot(tok::annot_pragma_openmp_end))
2218 if (isOpenMPLoopDirective(DKind))
2219 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2220 if (isOpenMPSimdDirective(DKind))
2221 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2222 ParseScope OMPDirectiveScope(this, ScopeFlags);
2223 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
2225 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2226 bool HasImplicitClause = false;
2227 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2228 HasImplicitClause = true;
2229 // Push copy of the current token back to stream to properly parse
2230 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2231 PP.EnterToken(Tok, /*IsReinject*/ true);
2232 PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2235 OpenMPClauseKind CKind = Tok.isAnnotation()
2237 : getOpenMPClauseKind(PP.getSpelling(Tok));
2238 if (HasImplicitClause) {
2239 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2240 if (DKind == OMPD_flush) {
2243 assert(DKind == OMPD_depobj &&
2244 "Expected flush or depobj directives.");
2245 CKind = OMPC_depobj;
2248 // No more implicit clauses allowed.
2249 ImplicitClauseAllowed = false;
2250 Actions.StartOpenMPClause(CKind);
2251 HasImplicitClause = false;
2253 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
2254 FirstClauses[CKind].setInt(true);
2256 FirstClauses[CKind].setPointer(Clause);
2257 Clauses.push_back(Clause);
2261 if (Tok.is(tok::comma))
2263 Actions.EndOpenMPClause();
2265 // End location of the directive.
2266 EndLoc = Tok.getLocation();
2267 // Consume final annot_pragma_openmp_end.
2268 ConsumeAnnotationToken();
2270 // OpenMP [2.13.8, ordered Construct, Syntax]
2271 // If the depend clause is specified, the ordered construct is a stand-alone
2273 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
2274 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2275 ParsedStmtContext()) {
2276 Diag(Loc, diag::err_omp_immediate_directive)
2277 << getOpenMPDirectiveName(DKind) << 1
2278 << getOpenMPClauseName(OMPC_depend);
2280 HasAssociatedStatement = false;
2283 StmtResult AssociatedStmt;
2284 if (HasAssociatedStatement) {
2285 // The body is a block scope like in Lambdas and Blocks.
2286 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
2287 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2288 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2289 // should have at least one compound statement scope within it.
2290 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
2291 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2292 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2293 DKind == OMPD_target_exit_data) {
2294 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
2295 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2296 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
2297 /*isStmtExpr=*/false));
2298 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2300 Directive = Actions.ActOnOpenMPExecutableDirective(
2301 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
2305 Actions.EndOpenMPDSABlock(Directive.get());
2306 OMPDirectiveScope.Exit();
2309 case OMPD_declare_simd:
2310 case OMPD_declare_target:
2311 case OMPD_end_declare_target:
2313 case OMPD_begin_declare_variant:
2314 case OMPD_end_declare_variant:
2315 case OMPD_declare_variant:
2316 Diag(Tok, diag::err_omp_unexpected_directive)
2317 << 1 << getOpenMPDirectiveName(DKind);
2318 SkipUntil(tok::annot_pragma_openmp_end);
2321 Diag(Tok, diag::err_omp_unknown_directive);
2322 SkipUntil(tok::annot_pragma_openmp_end);
2328 // Parses simple list:
2329 // simple-variable-list:
2330 // '(' id-expression {, id-expression} ')'
2332 bool Parser::ParseOpenMPSimpleVarList(
2333 OpenMPDirectiveKind Kind,
2334 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
2336 bool AllowScopeSpecifier) {
2338 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2339 if (T.expectAndConsume(diag::err_expected_lparen_after,
2340 getOpenMPDirectiveName(Kind).data()))
2342 bool IsCorrect = true;
2343 bool NoIdentIsFound = true;
2345 // Read tokens while ')' or annot_pragma_openmp_end is not found.
2346 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2350 Token PrevTok = Tok;
2351 NoIdentIsFound = false;
2353 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2354 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2355 /*ObjectHadErrors=*/false, false)) {
2357 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2359 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2360 /*ObjectHadErrors=*/false, false, false,
2361 false, false, nullptr, Name)) {
2363 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2365 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2366 Tok.isNot(tok::annot_pragma_openmp_end)) {
2368 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2370 Diag(PrevTok.getLocation(), diag::err_expected)
2372 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2374 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2377 if (Tok.is(tok::comma)) {
2382 if (NoIdentIsFound) {
2383 Diag(Tok, diag::err_expected) << tok::identifier;
2388 IsCorrect = !T.consumeClose() && IsCorrect;
2393 /// Parsing of OpenMP clauses.
2396 /// if-clause | final-clause | num_threads-clause | safelen-clause |
2397 /// default-clause | private-clause | firstprivate-clause | shared-clause
2398 /// | linear-clause | aligned-clause | collapse-clause |
2399 /// lastprivate-clause | reduction-clause | proc_bind-clause |
2400 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
2401 /// mergeable-clause | flush-clause | read-clause | write-clause |
2402 /// update-clause | capture-clause | seq_cst-clause | device-clause |
2403 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
2404 /// thread_limit-clause | priority-clause | grainsize-clause |
2405 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
2406 /// from-clause | is_device_ptr-clause | task_reduction-clause |
2407 /// in_reduction-clause | allocator-clause | allocate-clause |
2408 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
2409 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause |
2410 /// exclusive-clause
2412 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
2413 OpenMPClauseKind CKind, bool FirstClause) {
2414 OMPClause *Clause = nullptr;
2415 bool ErrorFound = false;
2416 bool WrongDirective = false;
2417 // Check if clause is allowed for the given directive.
2418 if (CKind != OMPC_unknown &&
2419 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
2420 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
2421 << getOpenMPDirectiveName(DKind);
2423 WrongDirective = true;
2428 case OMPC_num_threads:
2433 case OMPC_num_teams:
2434 case OMPC_thread_limit:
2436 case OMPC_grainsize:
2437 case OMPC_num_tasks:
2439 case OMPC_allocator:
2442 // OpenMP [2.5, Restrictions]
2443 // At most one num_threads clause can appear on the directive.
2444 // OpenMP [2.8.1, simd construct, Restrictions]
2445 // Only one safelen clause can appear on a simd directive.
2446 // Only one simdlen clause can appear on a simd directive.
2447 // Only one collapse clause can appear on a simd directive.
2448 // OpenMP [2.11.1, task Construct, Restrictions]
2449 // At most one if clause can appear on the directive.
2450 // At most one final clause can appear on the directive.
2451 // OpenMP [teams Construct, Restrictions]
2452 // At most one num_teams clause can appear on the directive.
2453 // At most one thread_limit clause can appear on the directive.
2454 // OpenMP [2.9.1, task Construct, Restrictions]
2455 // At most one priority clause can appear on the directive.
2456 // OpenMP [2.9.2, taskloop Construct, Restrictions]
2457 // At most one grainsize clause can appear on the directive.
2458 // OpenMP [2.9.2, taskloop Construct, Restrictions]
2459 // At most one num_tasks clause can appear on the directive.
2460 // OpenMP [2.11.3, allocate Directive, Restrictions]
2461 // At most one allocator clause can appear on the directive.
2462 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
2463 // At most one detach clause can appear on the directive.
2465 Diag(Tok, diag::err_omp_more_one_clause)
2466 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2470 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
2471 Clause = ParseOpenMPClause(CKind, WrongDirective);
2473 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
2476 case OMPC_proc_bind:
2477 case OMPC_atomic_default_mem_order:
2479 // OpenMP [2.14.3.1, Restrictions]
2480 // Only a single default clause may be specified on a parallel, task or
2482 // OpenMP [2.5, parallel Construct, Restrictions]
2483 // At most one proc_bind clause can appear on the directive.
2484 // OpenMP [5.0, Requires directive, Restrictions]
2485 // At most one atomic_default_mem_order clause can appear
2487 if (!FirstClause && CKind != OMPC_order) {
2488 Diag(Tok, diag::err_omp_more_one_clause)
2489 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2493 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
2497 case OMPC_dist_schedule:
2498 case OMPC_defaultmap:
2499 // OpenMP [2.7.1, Restrictions, p. 3]
2500 // Only one schedule clause can appear on a loop directive.
2501 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
2502 // At most one defaultmap clause can appear on the directive.
2503 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
2504 // At most one device clause can appear on the directive.
2505 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
2507 Diag(Tok, diag::err_omp_more_one_clause)
2508 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2513 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
2517 case OMPC_mergeable:
2529 case OMPC_unified_address:
2530 case OMPC_unified_shared_memory:
2531 case OMPC_reverse_offload:
2532 case OMPC_dynamic_allocators:
2534 // OpenMP [2.7.1, Restrictions, p. 9]
2535 // Only one ordered clause can appear on a loop directive.
2536 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
2537 // Only one nowait clause can appear on a for directive.
2538 // OpenMP [5.0, Requires directive, Restrictions]
2539 // Each of the requires clauses can appear at most once on the directive.
2541 Diag(Tok, diag::err_omp_more_one_clause)
2542 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2546 Clause = ParseOpenMPClause(CKind, WrongDirective);
2550 Diag(Tok, diag::err_omp_more_one_clause)
2551 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2555 Clause = (DKind == OMPD_depobj)
2556 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
2557 : ParseOpenMPClause(CKind, WrongDirective);
2560 case OMPC_firstprivate:
2561 case OMPC_lastprivate:
2563 case OMPC_reduction:
2564 case OMPC_task_reduction:
2565 case OMPC_in_reduction:
2569 case OMPC_copyprivate:
2575 case OMPC_use_device_ptr:
2576 case OMPC_is_device_ptr:
2578 case OMPC_nontemporal:
2579 case OMPC_inclusive:
2580 case OMPC_exclusive:
2581 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
2583 case OMPC_device_type:
2585 skipUntilPragmaOpenMPEnd(DKind);
2587 case OMPC_threadprivate:
2590 if (!WrongDirective)
2591 Diag(Tok, diag::err_omp_unexpected_clause)
2592 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
2593 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
2596 return ErrorFound ? nullptr : Clause;
2599 /// Parses simple expression in parens for single-expression clauses of OpenMP
2601 /// \param RLoc Returned location of right paren.
2602 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
2603 SourceLocation &RLoc,
2604 bool IsAddressOfOperand) {
2605 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2606 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
2609 SourceLocation ELoc = Tok.getLocation();
2610 ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
2612 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
2613 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2616 RLoc = Tok.getLocation();
2617 if (!T.consumeClose())
2618 RLoc = T.getCloseLocation();
2623 /// Parsing of OpenMP clauses with single expressions like 'final',
2624 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
2625 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
2629 /// 'final' '(' expression ')'
2631 /// num_threads-clause:
2632 /// 'num_threads' '(' expression ')'
2635 /// 'safelen' '(' expression ')'
2638 /// 'simdlen' '(' expression ')'
2640 /// collapse-clause:
2641 /// 'collapse' '(' expression ')'
2643 /// priority-clause:
2644 /// 'priority' '(' expression ')'
2646 /// grainsize-clause:
2647 /// 'grainsize' '(' expression ')'
2649 /// num_tasks-clause:
2650 /// 'num_tasks' '(' expression ')'
2653 /// 'hint' '(' expression ')'
2655 /// allocator-clause:
2656 /// 'allocator' '(' expression ')'
2659 /// 'detach' '(' event-handler-expression ')'
2661 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
2663 SourceLocation Loc = ConsumeToken();
2664 SourceLocation LLoc = Tok.getLocation();
2665 SourceLocation RLoc;
2667 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
2669 if (Val.isInvalid())
2674 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
2677 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
2680 /// 'default' '(' 'none' | 'shared' ')'
2682 /// proc_bind-clause:
2683 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')'
2686 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')'
2688 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
2690 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
2691 if (!Val || ParseOnly)
2693 return Actions.ActOnOpenMPSimpleClause(
2694 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
2695 Val.getValue().Loc, Val.getValue().RLoc);
2698 /// Parsing of OpenMP clauses like 'ordered'.
2709 /// mergeable-clause:
2724 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
2725 SourceLocation Loc = Tok.getLocation();
2730 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
2734 /// Parsing of OpenMP clauses with single expressions and some additional
2735 /// argument like 'schedule' or 'dist_schedule'.
2737 /// schedule-clause:
2738 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
2742 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
2745 /// 'defaultmap' '(' modifier ':' kind ')'
2748 /// 'device' '(' [ device-modifier ':' ] expression ')'
2750 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
2751 OpenMPClauseKind Kind,
2753 SourceLocation Loc = ConsumeToken();
2754 SourceLocation DelimLoc;
2756 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2757 if (T.expectAndConsume(diag::err_expected_lparen_after,
2758 getOpenMPClauseName(Kind)))
2762 SmallVector<unsigned, 4> Arg;
2763 SmallVector<SourceLocation, 4> KLoc;
2764 if (Kind == OMPC_schedule) {
2765 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
2766 Arg.resize(NumberOfElements);
2767 KLoc.resize(NumberOfElements);
2768 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
2769 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
2770 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
2771 unsigned KindModifier = getOpenMPSimpleClauseType(
2772 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2773 if (KindModifier > OMPC_SCHEDULE_unknown) {
2775 Arg[Modifier1] = KindModifier;
2776 KLoc[Modifier1] = Tok.getLocation();
2777 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2778 Tok.isNot(tok::annot_pragma_openmp_end))
2780 if (Tok.is(tok::comma)) {
2781 // Parse ',' 'modifier'
2783 KindModifier = getOpenMPSimpleClauseType(
2784 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2785 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
2787 : (unsigned)OMPC_SCHEDULE_unknown;
2788 KLoc[Modifier2] = Tok.getLocation();
2789 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2790 Tok.isNot(tok::annot_pragma_openmp_end))
2794 if (Tok.is(tok::colon))
2797 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
2798 KindModifier = getOpenMPSimpleClauseType(
2799 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2801 Arg[ScheduleKind] = KindModifier;
2802 KLoc[ScheduleKind] = Tok.getLocation();
2803 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2804 Tok.isNot(tok::annot_pragma_openmp_end))
2806 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
2807 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
2808 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
2810 DelimLoc = ConsumeAnyToken();
2811 } else if (Kind == OMPC_dist_schedule) {
2812 Arg.push_back(getOpenMPSimpleClauseType(
2813 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
2814 KLoc.push_back(Tok.getLocation());
2815 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2816 Tok.isNot(tok::annot_pragma_openmp_end))
2818 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
2819 DelimLoc = ConsumeAnyToken();
2820 } else if (Kind == OMPC_defaultmap) {
2821 // Get a defaultmap modifier
2822 unsigned Modifier = getOpenMPSimpleClauseType(
2823 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2824 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
2826 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
2827 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
2828 Arg.push_back(Modifier);
2829 KLoc.push_back(Tok.getLocation());
2830 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2831 Tok.isNot(tok::annot_pragma_openmp_end))
2834 if (Tok.is(tok::colon))
2836 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
2837 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
2838 // Get a defaultmap kind
2839 Arg.push_back(getOpenMPSimpleClauseType(
2840 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
2841 KLoc.push_back(Tok.getLocation());
2842 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2843 Tok.isNot(tok::annot_pragma_openmp_end))
2845 } else if (Kind == OMPC_device) {
2846 // Only target executable directives support extended device construct.
2847 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
2848 NextToken().is(tok::colon)) {
2849 // Parse optional <device modifier> ':'
2850 Arg.push_back(getOpenMPSimpleClauseType(
2851 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
2852 KLoc.push_back(Tok.getLocation());
2857 Arg.push_back(OMPC_DEVICE_unknown);
2858 KLoc.emplace_back();
2861 assert(Kind == OMPC_if);
2862 KLoc.push_back(Tok.getLocation());
2863 TentativeParsingAction TPA(*this);
2864 auto DK = parseOpenMPDirectiveKind(*this);
2866 if (DK != OMPD_unknown) {
2868 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
2870 DelimLoc = ConsumeToken();
2873 Arg.back() = unsigned(OMPD_unknown);
2880 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
2881 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
2882 Kind == OMPC_if || Kind == OMPC_device;
2883 if (NeedAnExpression) {
2884 SourceLocation ELoc = Tok.getLocation();
2885 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
2886 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
2888 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2892 SourceLocation RLoc = Tok.getLocation();
2893 if (!T.consumeClose())
2894 RLoc = T.getCloseLocation();
2896 if (NeedAnExpression && Val.isInvalid())
2901 return Actions.ActOnOpenMPSingleExprWithArgClause(
2902 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
2905 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
2906 UnqualifiedId &ReductionId) {
2907 if (ReductionIdScopeSpec.isEmpty()) {
2909 switch (P.getCurToken().getKind()) {
2937 if (OOK != OO_None) {
2938 SourceLocation OpLoc = P.ConsumeToken();
2939 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
2940 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
2944 return P.ParseUnqualifiedId(
2945 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
2946 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
2947 /*AllowDestructorName*/ false,
2948 /*AllowConstructorName*/ false,
2949 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
2952 /// Checks if the token is a valid map-type-modifier.
2953 static OpenMPMapModifierKind isMapModifier(Parser &P) {
2954 Token Tok = P.getCurToken();
2955 if (!Tok.is(tok::identifier))
2956 return OMPC_MAP_MODIFIER_unknown;
2958 Preprocessor &PP = P.getPreprocessor();
2959 OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
2960 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2961 return TypeModifier;
2964 /// Parse the mapper modifier in map, to, and from clauses.
2965 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
2967 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
2968 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
2969 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2973 // Parse mapper-identifier
2974 if (getLangOpts().CPlusPlus)
2975 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2976 /*ObjectType=*/nullptr,
2977 /*ObjectHadErrors=*/false,
2978 /*EnteringContext=*/false);
2979 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
2980 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
2981 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2985 auto &DeclNames = Actions.getASTContext().DeclarationNames;
2986 Data.ReductionOrMapperId = DeclarationNameInfo(
2987 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
2990 return T.consumeClose();
2993 /// Parse map-type-modifiers in map clause.
2994 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2995 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
2996 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
2997 while (getCurToken().isNot(tok::colon)) {
2998 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
2999 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
3000 TypeModifier == OMPC_MAP_MODIFIER_close) {
3001 Data.MapTypeModifiers.push_back(TypeModifier);
3002 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
3004 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
3005 Data.MapTypeModifiers.push_back(TypeModifier);
3006 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
3008 if (parseMapperModifier(Data))
3011 // For the case of unknown map-type-modifier or a map-type.
3012 // Map-type is followed by a colon; the function returns when it
3013 // encounters a token followed by a colon.
3014 if (Tok.is(tok::comma)) {
3015 Diag(Tok, diag::err_omp_map_type_modifier_missing);
3019 // Potential map-type token as it is followed by a colon.
3020 if (PP.LookAhead(0).is(tok::colon))
3022 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
3025 if (getCurToken().is(tok::comma))
3031 /// Checks if the token is a valid map-type.
3032 static OpenMPMapClauseKind isMapType(Parser &P) {
3033 Token Tok = P.getCurToken();
3034 // The map-type token can be either an identifier or the C++ delete keyword.
3035 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
3036 return OMPC_MAP_unknown;
3037 Preprocessor &PP = P.getPreprocessor();
3038 OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
3039 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
3043 /// Parse map-type in map clause.
3044 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
3045 /// where, map-type ::= to | from | tofrom | alloc | release | delete
3046 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
3047 Token Tok = P.getCurToken();
3048 if (Tok.is(tok::colon)) {
3049 P.Diag(Tok, diag::err_omp_map_type_missing);
3052 Data.ExtraModifier = isMapType(P);
3053 if (Data.ExtraModifier == OMPC_MAP_unknown)
3054 P.Diag(Tok, diag::err_omp_unknown_map_type);
3058 /// Parses simple expression in parens for single-expression clauses of OpenMP
3060 /// \param RLoc Returned location of right paren.
3061 ExprResult Parser::ParseOpenMPIteratorsExpr() {
3062 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
3063 "Expected 'iterator' token.");
3064 SourceLocation IteratorKwLoc = ConsumeToken();
3066 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3067 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
3070 SourceLocation LLoc = T.getOpenLocation();
3071 SmallVector<Sema::OMPIteratorData, 4> Data;
3072 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
3073 // Check if the type parsing is required.
3074 ParsedType IteratorType;
3075 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
3076 // identifier '=' is not found - parse type.
3077 TypeResult TR = ParseTypeName();
3078 if (TR.isInvalid()) {
3082 IteratorType = TR.get();
3085 // Parse identifier.
3086 IdentifierInfo *II = nullptr;
3087 SourceLocation IdLoc;
3088 if (Tok.is(tok::identifier)) {
3089 II = Tok.getIdentifierInfo();
3090 IdLoc = ConsumeToken();
3092 Diag(Tok, diag::err_expected_unqualified_id) << 0;
3096 SourceLocation AssignLoc;
3097 if (Tok.is(tok::equal))
3098 AssignLoc = ConsumeToken();
3100 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
3102 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
3103 ColonProtectionRAIIObject ColonRAII(*this);
3105 SourceLocation Loc = Tok.getLocation();
3106 ExprResult LHS = ParseCastExpression(AnyCastExpr);
3107 ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
3108 ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3109 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
3110 /*DiscardedValue=*/false);
3112 SourceLocation ColonLoc;
3113 if (Tok.is(tok::colon))
3114 ColonLoc = ConsumeToken();
3117 Loc = Tok.getLocation();
3118 LHS = ParseCastExpression(AnyCastExpr);
3119 ExprResult End = Actions.CorrectDelayedTyposInExpr(
3120 ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3121 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
3122 /*DiscardedValue=*/false);
3124 SourceLocation SecColonLoc;
3126 // Parse optional step.
3127 if (Tok.is(tok::colon)) {
3129 SecColonLoc = ConsumeToken();
3131 Loc = Tok.getLocation();
3132 LHS = ParseCastExpression(AnyCastExpr);
3133 Step = Actions.CorrectDelayedTyposInExpr(
3134 ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3135 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
3136 /*DiscardedValue=*/false);
3140 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3141 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
3142 if (Tok.is(tok::comma))
3145 Sema::OMPIteratorData &D = Data.emplace_back();
3147 D.DeclIdentLoc = IdLoc;
3148 D.Type = IteratorType;
3149 D.AssignLoc = AssignLoc;
3150 D.ColonLoc = ColonLoc;
3151 D.SecColonLoc = SecColonLoc;
3152 D.Range.Begin = Begin.get();
3153 D.Range.End = End.get();
3154 D.Range.Step = Step.get();
3158 SourceLocation RLoc = Tok.getLocation();
3159 if (!T.consumeClose())
3160 RLoc = T.getCloseLocation();
3162 return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc,
3166 /// Parses clauses with list.
3167 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
3168 OpenMPClauseKind Kind,
3169 SmallVectorImpl<Expr *> &Vars,
3170 OpenMPVarListDataTy &Data) {
3171 UnqualifiedId UnqualifiedReductionId;
3172 bool InvalidReductionId = false;
3173 bool IsInvalidMapperModifier = false;
3176 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3177 if (T.expectAndConsume(diag::err_expected_lparen_after,
3178 getOpenMPClauseName(Kind)))
3181 bool DependWithIterator = false;
3182 bool NeedRParenForLinear = false;
3183 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
3184 tok::annot_pragma_openmp_end);
3185 // Handle reduction-identifier for reduction clause.
3186 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
3187 Kind == OMPC_in_reduction) {
3188 Data.ExtraModifier = OMPC_REDUCTION_unknown;
3189 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
3190 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
3191 NextToken().is(tok::comma)) {
3192 // Parse optional reduction modifier.
3193 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
3194 Data.ExtraModifierLoc = Tok.getLocation();
3196 assert(Tok.is(tok::comma) && "Expected comma.");
3197 (void)ConsumeToken();
3199 ColonProtectionRAIIObject ColonRAII(*this);
3200 if (getLangOpts().CPlusPlus)
3201 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
3202 /*ObjectType=*/nullptr,
3203 /*ObjectHadErrors=*/false,
3204 /*EnteringContext=*/false);
3205 InvalidReductionId = ParseReductionId(
3206 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
3207 if (InvalidReductionId) {
3208 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3211 if (Tok.is(tok::colon))
3212 Data.ColonLoc = ConsumeToken();
3214 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
3215 if (!InvalidReductionId)
3216 Data.ReductionOrMapperId =
3217 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
3218 } else if (Kind == OMPC_depend) {
3219 if (getLangOpts().OpenMP >= 50) {
3220 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
3221 // Handle optional dependence modifier.
3222 // iterator(iterators-definition)
3223 // where iterators-definition is iterator-specifier [,
3224 // iterators-definition ]
3225 // where iterator-specifier is [ iterator-type ] identifier =
3226 // range-specification
3227 DependWithIterator = true;
3228 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
3229 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
3230 Data.DepModOrTailExpr = IteratorRes.get();
3232 ExpectAndConsume(tok::comma);
3235 // Handle dependency type for depend clause.
3236 ColonProtectionRAIIObject ColonRAII(*this);
3237 Data.ExtraModifier = getOpenMPSimpleClauseType(
3238 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "");
3239 Data.ExtraModifierLoc = Tok.getLocation();
3240 if (Data.ExtraModifier == OMPC_DEPEND_unknown) {
3241 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3245 // Special processing for depend(source) clause.
3246 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {
3252 if (Tok.is(tok::colon)) {
3253 Data.ColonLoc = ConsumeToken();
3255 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
3256 : diag::warn_pragma_expected_colon)
3257 << "dependency type";
3259 } else if (Kind == OMPC_linear) {
3260 // Try to parse modifier if any.
3261 Data.ExtraModifier = OMPC_LINEAR_val;
3262 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
3263 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
3264 Data.ExtraModifierLoc = ConsumeToken();
3265 LinearT.consumeOpen();
3266 NeedRParenForLinear = true;
3268 } else if (Kind == OMPC_lastprivate) {
3269 // Try to parse modifier if any.
3270 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
3271 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
3272 // distribute and taskloop based directives.
3273 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
3274 !isOpenMPTaskLoopDirective(DKind)) &&
3275 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
3276 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
3277 Data.ExtraModifierLoc = Tok.getLocation();
3279 assert(Tok.is(tok::colon) && "Expected colon.");
3280 Data.ColonLoc = ConsumeToken();
3282 } else if (Kind == OMPC_map) {
3283 // Handle map type for map clause.
3284 ColonProtectionRAIIObject ColonRAII(*this);
3286 // The first identifier may be a list item, a map-type or a
3287 // map-type-modifier. The map-type can also be delete which has the same
3288 // spelling of the C++ delete keyword.
3289 Data.ExtraModifier = OMPC_MAP_unknown;
3290 Data.ExtraModifierLoc = Tok.getLocation();
3292 // Check for presence of a colon in the map clause.
3293 TentativeParsingAction TPA(*this);
3294 bool ColonPresent = false;
3295 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3297 if (Tok.is(tok::colon))
3298 ColonPresent = true;
3301 // Only parse map-type-modifier[s] and map-type if a colon is present in
3304 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
3305 if (!IsInvalidMapperModifier)
3306 parseMapType(*this, Data);
3308 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
3310 if (Data.ExtraModifier == OMPC_MAP_unknown) {
3311 Data.ExtraModifier = OMPC_MAP_tofrom;
3312 Data.IsMapTypeImplicit = true;
3315 if (Tok.is(tok::colon))
3316 Data.ColonLoc = ConsumeToken();
3317 } else if (Kind == OMPC_to || Kind == OMPC_from) {
3318 if (Tok.is(tok::identifier)) {
3319 bool IsMapperModifier = false;
3320 if (Kind == OMPC_to) {
3321 auto Modifier = static_cast<OpenMPToModifierKind>(
3322 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
3323 if (Modifier == OMPC_TO_MODIFIER_mapper)
3324 IsMapperModifier = true;
3326 auto Modifier = static_cast<OpenMPFromModifierKind>(
3327 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
3328 if (Modifier == OMPC_FROM_MODIFIER_mapper)
3329 IsMapperModifier = true;
3331 if (IsMapperModifier) {
3332 // Parse the mapper modifier.
3334 IsInvalidMapperModifier = parseMapperModifier(Data);
3335 if (Tok.isNot(tok::colon)) {
3336 if (!IsInvalidMapperModifier)
3337 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
3338 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3342 if (Tok.is(tok::colon))
3346 } else if (Kind == OMPC_allocate) {
3347 // Handle optional allocator expression followed by colon delimiter.
3348 ColonProtectionRAIIObject ColonRAII(*this);
3349 TentativeParsingAction TPA(*this);
3351 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3352 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
3353 /*DiscardedValue=*/false);
3354 if (Tail.isUsable()) {
3355 if (Tok.is(tok::colon)) {
3356 Data.DepModOrTailExpr = Tail.get();
3357 Data.ColonLoc = ConsumeToken();
3360 // colon not found, no allocator specified, parse only list of
3365 // Parsing was unsuccessfull, revert and skip to the end of clause or
3368 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3374 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
3375 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
3376 (Kind == OMPC_reduction && !InvalidReductionId) ||
3377 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
3378 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
3379 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
3380 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
3381 Tok.isNot(tok::annot_pragma_openmp_end))) {
3382 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
3383 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
3385 ExprResult VarExpr =
3386 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3387 if (VarExpr.isUsable()) {
3388 Vars.push_back(VarExpr.get());
3390 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3394 IsComma = Tok.is(tok::comma);
3397 else if (Tok.isNot(tok::r_paren) &&
3398 Tok.isNot(tok::annot_pragma_openmp_end) &&
3399 (!MayHaveTail || Tok.isNot(tok::colon)))
3400 Diag(Tok, diag::err_omp_expected_punc)
3401 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
3402 : getOpenMPClauseName(Kind))
3403 << (Kind == OMPC_flush);
3406 // Parse ')' for linear clause with modifier.
3407 if (NeedRParenForLinear)
3408 LinearT.consumeClose();
3410 // Parse ':' linear-step (or ':' alignment).
3411 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
3413 Data.ColonLoc = Tok.getLocation();
3414 SourceLocation ELoc = ConsumeToken();
3415 ExprResult Tail = ParseAssignmentExpression();
3417 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
3418 if (Tail.isUsable())
3419 Data.DepModOrTailExpr = Tail.get();
3421 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3426 Data.RLoc = Tok.getLocation();
3427 if (!T.consumeClose())
3428 Data.RLoc = T.getCloseLocation();
3429 // Exit from scope when the iterator is used in depend clause.
3430 if (DependWithIterator)
3432 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
3433 (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId ||
3434 IsInvalidMapperModifier;
3437 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
3438 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
3439 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
3442 /// 'private' '(' list ')'
3443 /// firstprivate-clause:
3444 /// 'firstprivate' '(' list ')'
3445 /// lastprivate-clause:
3446 /// 'lastprivate' '(' list ')'
3448 /// 'shared' '(' list ')'
3450 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
3452 /// 'aligned' '(' list [ ':' alignment ] ')'
3453 /// reduction-clause:
3454 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
3455 /// task_reduction-clause:
3456 /// 'task_reduction' '(' reduction-identifier ':' list ')'
3457 /// in_reduction-clause:
3458 /// 'in_reduction' '(' reduction-identifier ':' list ')'
3459 /// copyprivate-clause:
3460 /// 'copyprivate' '(' list ')'
3462 /// 'flush' '(' list ')'
3464 /// 'depend' '(' in | out | inout : list | source ')'
3466 /// 'map' '(' [ [ always [,] ] [ close [,] ]
3467 /// [ mapper '(' mapper-identifier ')' [,] ]
3468 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
3470 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
3472 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
3473 /// use_device_ptr-clause:
3474 /// 'use_device_ptr' '(' list ')'
3475 /// is_device_ptr-clause:
3476 /// 'is_device_ptr' '(' list ')'
3477 /// allocate-clause:
3478 /// 'allocate' '(' [ allocator ':' ] list ')'
3479 /// nontemporal-clause:
3480 /// 'nontemporal' '(' list ')'
3481 /// inclusive-clause:
3482 /// 'inclusive' '(' list ')'
3483 /// exclusive-clause:
3484 /// 'exclusive' '(' list ')'
3486 /// For 'linear' clause linear-list may have the following forms:
3489 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
3490 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
3491 OpenMPClauseKind Kind,
3493 SourceLocation Loc = Tok.getLocation();
3494 SourceLocation LOpen = ConsumeToken();
3495 SmallVector<Expr *, 4> Vars;
3496 OpenMPVarListDataTy Data;
3498 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
3503 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
3504 return Actions.ActOnOpenMPVarListClause(
3505 Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc,
3506 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
3507 Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
3508 Data.IsMapTypeImplicit, Data.ExtraModifierLoc);