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/OpenMPClause.h"
15 #include "clang/AST/StmtOpenMP.h"
16 #include "clang/Basic/OpenMPKinds.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Basic/TokenKinds.h"
19 #include "clang/Parse/ParseDiagnostic.h"
20 #include "clang/Parse/Parser.h"
21 #include "clang/Parse/RAIIObjectsForParser.h"
22 #include "clang/Sema/EnterExpressionEvaluationContext.h"
23 #include "clang/Sema/Scope.h"
24 #include "llvm/ADT/PointerIntPair.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/ADT/UniqueVector.h"
27 #include "llvm/Frontend/OpenMP/OMPAssume.h"
28 #include "llvm/Frontend/OpenMP/OMPContext.h"
31 using namespace clang
;
32 using namespace llvm::omp
;
34 //===----------------------------------------------------------------------===//
35 // OpenMP declarative directives.
36 //===----------------------------------------------------------------------===//
39 enum OpenMPDirectiveKindEx
{
40 OMPD_cancellation
= llvm::omp::Directive_enumSize
+ 1,
52 OMPD_distribute_parallel
,
53 OMPD_teams_distribute_parallel
,
54 OMPD_target_teams_distribute_parallel
,
61 // Helper to unify the enum class OpenMPDirectiveKind with its extension
62 // the OpenMPDirectiveKindEx enum which allows to use them together as if they
63 // are unsigned values.
64 struct OpenMPDirectiveKindExWrapper
{
65 OpenMPDirectiveKindExWrapper(unsigned Value
) : Value(Value
) {}
66 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK
) : Value(unsigned(DK
)) {}
67 bool operator==(OpenMPDirectiveKindExWrapper V
) const {
68 return Value
== V
.Value
;
70 bool operator!=(OpenMPDirectiveKindExWrapper V
) const {
71 return Value
!= V
.Value
;
73 bool operator==(OpenMPDirectiveKind V
) const { return Value
== unsigned(V
); }
74 bool operator!=(OpenMPDirectiveKind V
) const { return Value
!= unsigned(V
); }
75 bool operator<(OpenMPDirectiveKind V
) const { return Value
< unsigned(V
); }
76 operator unsigned() const { return Value
; }
77 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value
); }
81 class DeclDirectiveListParserHelper final
{
82 SmallVector
<Expr
*, 4> Identifiers
;
84 OpenMPDirectiveKind Kind
;
87 DeclDirectiveListParserHelper(Parser
*P
, OpenMPDirectiveKind Kind
)
89 void operator()(CXXScopeSpec
&SS
, DeclarationNameInfo NameInfo
) {
90 ExprResult Res
= P
->getActions().ActOnOpenMPIdExpression(
91 P
->getCurScope(), SS
, NameInfo
, Kind
);
93 Identifiers
.push_back(Res
.get());
95 llvm::ArrayRef
<Expr
*> getIdentifiers() const { return Identifiers
; }
99 // Map token string to extended OMP token kind that are
100 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
101 static unsigned getOpenMPDirectiveKindEx(StringRef S
) {
102 OpenMPDirectiveKindExWrapper DKind
= getOpenMPDirectiveKind(S
);
103 if (DKind
!= OMPD_unknown
)
106 return llvm::StringSwitch
<OpenMPDirectiveKindExWrapper
>(S
)
107 .Case("cancellation", OMPD_cancellation
)
108 .Case("data", OMPD_data
)
109 .Case("declare", OMPD_declare
)
110 .Case("end", OMPD_end
)
111 .Case("enter", OMPD_enter
)
112 .Case("exit", OMPD_exit
)
113 .Case("point", OMPD_point
)
114 .Case("reduction", OMPD_reduction
)
115 .Case("update", OMPD_update
)
116 .Case("mapper", OMPD_mapper
)
117 .Case("variant", OMPD_variant
)
118 .Case("begin", OMPD_begin
)
119 .Default(OMPD_unknown
);
122 static OpenMPDirectiveKindExWrapper
parseOpenMPDirectiveKind(Parser
&P
) {
123 // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
124 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
125 // TODO: add other combined directives in topological order.
126 static const OpenMPDirectiveKindExWrapper F
[][3] = {
127 {OMPD_begin
, OMPD_declare
, OMPD_begin_declare
},
128 {OMPD_begin
, OMPD_assumes
, OMPD_begin_assumes
},
129 {OMPD_end
, OMPD_declare
, OMPD_end_declare
},
130 {OMPD_end
, OMPD_assumes
, OMPD_end_assumes
},
131 {OMPD_cancellation
, OMPD_point
, OMPD_cancellation_point
},
132 {OMPD_declare
, OMPD_reduction
, OMPD_declare_reduction
},
133 {OMPD_declare
, OMPD_mapper
, OMPD_declare_mapper
},
134 {OMPD_declare
, OMPD_simd
, OMPD_declare_simd
},
135 {OMPD_declare
, OMPD_target
, OMPD_declare_target
},
136 {OMPD_declare
, OMPD_variant
, OMPD_declare_variant
},
137 {OMPD_begin_declare
, OMPD_target
, OMPD_begin_declare_target
},
138 {OMPD_begin_declare
, OMPD_variant
, OMPD_begin_declare_variant
},
139 {OMPD_end_declare
, OMPD_variant
, OMPD_end_declare_variant
},
140 {OMPD_distribute
, OMPD_parallel
, OMPD_distribute_parallel
},
141 {OMPD_distribute_parallel
, OMPD_for
, OMPD_distribute_parallel_for
},
142 {OMPD_distribute_parallel_for
, OMPD_simd
,
143 OMPD_distribute_parallel_for_simd
},
144 {OMPD_distribute
, OMPD_simd
, OMPD_distribute_simd
},
145 {OMPD_end_declare
, OMPD_target
, OMPD_end_declare_target
},
146 {OMPD_target
, OMPD_data
, OMPD_target_data
},
147 {OMPD_target
, OMPD_enter
, OMPD_target_enter
},
148 {OMPD_target
, OMPD_exit
, OMPD_target_exit
},
149 {OMPD_target
, OMPD_update
, OMPD_target_update
},
150 {OMPD_target_enter
, OMPD_data
, OMPD_target_enter_data
},
151 {OMPD_target_exit
, OMPD_data
, OMPD_target_exit_data
},
152 {OMPD_for
, OMPD_simd
, OMPD_for_simd
},
153 {OMPD_parallel
, OMPD_for
, OMPD_parallel_for
},
154 {OMPD_parallel_for
, OMPD_simd
, OMPD_parallel_for_simd
},
155 {OMPD_parallel
, OMPD_loop
, OMPD_parallel_loop
},
156 {OMPD_parallel
, OMPD_sections
, OMPD_parallel_sections
},
157 {OMPD_taskloop
, OMPD_simd
, OMPD_taskloop_simd
},
158 {OMPD_target
, OMPD_parallel
, OMPD_target_parallel
},
159 {OMPD_target
, OMPD_simd
, OMPD_target_simd
},
160 {OMPD_target_parallel
, OMPD_loop
, OMPD_target_parallel_loop
},
161 {OMPD_target_parallel
, OMPD_for
, OMPD_target_parallel_for
},
162 {OMPD_target_parallel_for
, OMPD_simd
, OMPD_target_parallel_for_simd
},
163 {OMPD_teams
, OMPD_distribute
, OMPD_teams_distribute
},
164 {OMPD_teams_distribute
, OMPD_simd
, OMPD_teams_distribute_simd
},
165 {OMPD_teams_distribute
, OMPD_parallel
, OMPD_teams_distribute_parallel
},
166 {OMPD_teams_distribute_parallel
, OMPD_for
,
167 OMPD_teams_distribute_parallel_for
},
168 {OMPD_teams_distribute_parallel_for
, OMPD_simd
,
169 OMPD_teams_distribute_parallel_for_simd
},
170 {OMPD_teams
, OMPD_loop
, OMPD_teams_loop
},
171 {OMPD_target
, OMPD_teams
, OMPD_target_teams
},
172 {OMPD_target_teams
, OMPD_distribute
, OMPD_target_teams_distribute
},
173 {OMPD_target_teams
, OMPD_loop
, OMPD_target_teams_loop
},
174 {OMPD_target_teams_distribute
, OMPD_parallel
,
175 OMPD_target_teams_distribute_parallel
},
176 {OMPD_target_teams_distribute
, OMPD_simd
,
177 OMPD_target_teams_distribute_simd
},
178 {OMPD_target_teams_distribute_parallel
, OMPD_for
,
179 OMPD_target_teams_distribute_parallel_for
},
180 {OMPD_target_teams_distribute_parallel_for
, OMPD_simd
,
181 OMPD_target_teams_distribute_parallel_for_simd
},
182 {OMPD_master
, OMPD_taskloop
, OMPD_master_taskloop
},
183 {OMPD_masked
, OMPD_taskloop
, OMPD_masked_taskloop
},
184 {OMPD_master_taskloop
, OMPD_simd
, OMPD_master_taskloop_simd
},
185 {OMPD_masked_taskloop
, OMPD_simd
, OMPD_masked_taskloop_simd
},
186 {OMPD_parallel
, OMPD_master
, OMPD_parallel_master
},
187 {OMPD_parallel
, OMPD_masked
, OMPD_parallel_masked
},
188 {OMPD_parallel_master
, OMPD_taskloop
, OMPD_parallel_master_taskloop
},
189 {OMPD_parallel_masked
, OMPD_taskloop
, OMPD_parallel_masked_taskloop
},
190 {OMPD_parallel_master_taskloop
, OMPD_simd
,
191 OMPD_parallel_master_taskloop_simd
},
192 {OMPD_parallel_masked_taskloop
, OMPD_simd
,
193 OMPD_parallel_masked_taskloop_simd
}};
194 enum { CancellationPoint
= 0, DeclareReduction
= 1, TargetData
= 2 };
195 Token Tok
= P
.getCurToken();
196 OpenMPDirectiveKindExWrapper DKind
=
198 ? static_cast<unsigned>(OMPD_unknown
)
199 : getOpenMPDirectiveKindEx(P
.getPreprocessor().getSpelling(Tok
));
200 if (DKind
== OMPD_unknown
)
203 for (const auto &I
: F
) {
207 Tok
= P
.getPreprocessor().LookAhead(0);
208 OpenMPDirectiveKindExWrapper SDKind
=
210 ? static_cast<unsigned>(OMPD_unknown
)
211 : getOpenMPDirectiveKindEx(P
.getPreprocessor().getSpelling(Tok
));
212 if (SDKind
== OMPD_unknown
)
215 if (SDKind
== I
[1]) {
220 return unsigned(DKind
) < llvm::omp::Directive_enumSize
221 ? static_cast<OpenMPDirectiveKind
>(DKind
)
225 static DeclarationName
parseOpenMPReductionId(Parser
&P
) {
226 Token Tok
= P
.getCurToken();
227 Sema
&Actions
= P
.getActions();
228 OverloadedOperatorKind OOK
= OO_None
;
229 // Allow to use 'operator' keyword for C++ operators
230 bool WithOperator
= false;
231 if (Tok
.is(tok::kw_operator
)) {
233 Tok
= P
.getCurToken();
236 switch (Tok
.getKind()) {
237 case tok::plus
: // '+'
240 case tok::minus
: // '-'
243 case tok::star
: // '*'
246 case tok::amp
: // '&'
249 case tok::pipe
: // '|'
252 case tok::caret
: // '^'
255 case tok::ampamp
: // '&&'
258 case tok::pipepipe
: // '||'
261 case tok::identifier
: // identifier
266 P
.Diag(Tok
.getLocation(), diag::err_omp_expected_reduction_identifier
);
267 P
.SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
268 Parser::StopBeforeMatch
);
269 return DeclarationName();
272 auto &DeclNames
= Actions
.getASTContext().DeclarationNames
;
273 return OOK
== OO_None
? DeclNames
.getIdentifier(Tok
.getIdentifierInfo())
274 : DeclNames
.getCXXOperatorName(OOK
);
277 /// Parse 'omp declare reduction' construct.
279 /// declare-reduction-directive:
280 /// annot_pragma_openmp 'declare' 'reduction'
281 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
282 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
283 /// annot_pragma_openmp_end
284 /// <reduction_id> is either a base language identifier or one of the following
285 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
287 Parser::DeclGroupPtrTy
288 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS
) {
290 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
291 if (T
.expectAndConsume(
292 diag::err_expected_lparen_after
,
293 getOpenMPDirectiveName(OMPD_declare_reduction
).data())) {
294 SkipUntil(tok::annot_pragma_openmp_end
, StopBeforeMatch
);
295 return DeclGroupPtrTy();
298 DeclarationName Name
= parseOpenMPReductionId(*this);
299 if (Name
.isEmpty() && Tok
.is(tok::annot_pragma_openmp_end
))
300 return DeclGroupPtrTy();
303 bool IsCorrect
= !ExpectAndConsume(tok::colon
);
305 if (!IsCorrect
&& Tok
.is(tok::annot_pragma_openmp_end
))
306 return DeclGroupPtrTy();
308 IsCorrect
= IsCorrect
&& !Name
.isEmpty();
310 if (Tok
.is(tok::colon
) || Tok
.is(tok::annot_pragma_openmp_end
)) {
311 Diag(Tok
.getLocation(), diag::err_expected_type
);
315 if (!IsCorrect
&& Tok
.is(tok::annot_pragma_openmp_end
))
316 return DeclGroupPtrTy();
318 SmallVector
<std::pair
<QualType
, SourceLocation
>, 8> ReductionTypes
;
319 // Parse list of types until ':' token.
321 ColonProtectionRAIIObject
ColonRAII(*this);
323 TypeResult TR
= ParseTypeName(&Range
, DeclaratorContext::Prototype
, AS
);
325 QualType ReductionType
=
326 Actions
.ActOnOpenMPDeclareReductionType(Range
.getBegin(), TR
);
327 if (!ReductionType
.isNull()) {
328 ReductionTypes
.push_back(
329 std::make_pair(ReductionType
, Range
.getBegin()));
332 SkipUntil(tok::comma
, tok::colon
, tok::annot_pragma_openmp_end
,
336 if (Tok
.is(tok::colon
) || Tok
.is(tok::annot_pragma_openmp_end
))
340 if (ExpectAndConsume(tok::comma
)) {
342 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
343 Diag(Tok
.getLocation(), diag::err_expected_type
);
344 return DeclGroupPtrTy();
347 } while (Tok
.isNot(tok::annot_pragma_openmp_end
));
349 if (ReductionTypes
.empty()) {
350 SkipUntil(tok::annot_pragma_openmp_end
, StopBeforeMatch
);
351 return DeclGroupPtrTy();
354 if (!IsCorrect
&& Tok
.is(tok::annot_pragma_openmp_end
))
355 return DeclGroupPtrTy();
358 if (ExpectAndConsume(tok::colon
))
361 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
362 Diag(Tok
.getLocation(), diag::err_expected_expression
);
363 return DeclGroupPtrTy();
366 DeclGroupPtrTy DRD
= Actions
.ActOnOpenMPDeclareReductionDirectiveStart(
367 getCurScope(), Actions
.getCurLexicalContext(), Name
, ReductionTypes
, AS
);
369 // Parse <combiner> expression and then parse initializer if any for each
371 unsigned I
= 0, E
= ReductionTypes
.size();
372 for (Decl
*D
: DRD
.get()) {
373 TentativeParsingAction
TPA(*this);
374 ParseScope
OMPDRScope(this, Scope::FnScope
| Scope::DeclScope
|
375 Scope::CompoundStmtScope
|
376 Scope::OpenMPDirectiveScope
);
377 // Parse <combiner> expression.
378 Actions
.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D
);
379 ExprResult CombinerResult
= Actions
.ActOnFinishFullExpr(
380 ParseExpression().get(), D
->getLocation(), /*DiscardedValue*/ false);
381 Actions
.ActOnOpenMPDeclareReductionCombinerEnd(D
, CombinerResult
.get());
383 if (CombinerResult
.isInvalid() && Tok
.isNot(tok::r_paren
) &&
384 Tok
.isNot(tok::annot_pragma_openmp_end
)) {
389 IsCorrect
= !T
.consumeClose() && IsCorrect
&& CombinerResult
.isUsable();
390 ExprResult InitializerResult
;
391 if (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
392 // Parse <initializer> expression.
393 if (Tok
.is(tok::identifier
) &&
394 Tok
.getIdentifierInfo()->isStr("initializer")) {
397 Diag(Tok
.getLocation(), diag::err_expected
) << "'initializer'";
403 BalancedDelimiterTracker
T(*this, tok::l_paren
,
404 tok::annot_pragma_openmp_end
);
406 !T
.expectAndConsume(diag::err_expected_lparen_after
, "initializer") &&
408 if (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
409 ParseScope
OMPDRScope(this, Scope::FnScope
| Scope::DeclScope
|
410 Scope::CompoundStmtScope
|
411 Scope::OpenMPDirectiveScope
);
413 VarDecl
*OmpPrivParm
=
414 Actions
.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
416 // Check if initializer is omp_priv <init_expr> or something else.
417 if (Tok
.is(tok::identifier
) &&
418 Tok
.getIdentifierInfo()->isStr("omp_priv")) {
420 ParseOpenMPReductionInitializerForDecl(OmpPrivParm
);
422 InitializerResult
= Actions
.ActOnFinishFullExpr(
423 ParseAssignmentExpression().get(), D
->getLocation(),
424 /*DiscardedValue*/ false);
426 Actions
.ActOnOpenMPDeclareReductionInitializerEnd(
427 D
, InitializerResult
.get(), OmpPrivParm
);
428 if (InitializerResult
.isInvalid() && Tok
.isNot(tok::r_paren
) &&
429 Tok
.isNot(tok::annot_pragma_openmp_end
)) {
435 !T
.consumeClose() && IsCorrect
&& !InitializerResult
.isInvalid();
440 // Revert parsing if not the last type, otherwise accept it, we're done with
447 return Actions
.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD
,
451 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl
*OmpPrivParm
) {
452 // Parse declarator '=' initializer.
453 // If a '==' or '+=' is found, suggest a fixit to '='.
454 if (isTokenEqualOrEqualTypo()) {
457 if (Tok
.is(tok::code_completion
)) {
459 Actions
.CodeCompleteInitializer(getCurScope(), OmpPrivParm
);
460 Actions
.FinalizeDeclaration(OmpPrivParm
);
464 PreferredType
.enterVariableInit(Tok
.getLocation(), OmpPrivParm
);
465 ExprResult Init
= ParseInitializer();
467 if (Init
.isInvalid()) {
468 SkipUntil(tok::r_paren
, tok::annot_pragma_openmp_end
, StopBeforeMatch
);
469 Actions
.ActOnInitializerError(OmpPrivParm
);
471 Actions
.AddInitializerToDecl(OmpPrivParm
, Init
.get(),
472 /*DirectInit=*/false);
474 } else if (Tok
.is(tok::l_paren
)) {
475 // Parse C++ direct initializer: '(' expression-list ')'
476 BalancedDelimiterTracker
T(*this, tok::l_paren
);
481 SourceLocation LParLoc
= T
.getOpenLocation();
482 auto RunSignatureHelp
= [this, OmpPrivParm
, LParLoc
, &Exprs
]() {
483 QualType PreferredType
= Actions
.ProduceConstructorSignatureHelp(
484 OmpPrivParm
->getType()->getCanonicalTypeInternal(),
485 OmpPrivParm
->getLocation(), Exprs
, LParLoc
, /*Braced=*/false);
486 CalledSignatureHelp
= true;
487 return PreferredType
;
489 if (ParseExpressionList(Exprs
, [&] {
490 PreferredType
.enterFunctionArgument(Tok
.getLocation(),
493 if (PP
.isCodeCompletionReached() && !CalledSignatureHelp
)
495 Actions
.ActOnInitializerError(OmpPrivParm
);
496 SkipUntil(tok::r_paren
, tok::annot_pragma_openmp_end
, StopBeforeMatch
);
499 SourceLocation RLoc
= Tok
.getLocation();
500 if (!T
.consumeClose())
501 RLoc
= T
.getCloseLocation();
503 ExprResult Initializer
=
504 Actions
.ActOnParenListExpr(T
.getOpenLocation(), RLoc
, Exprs
);
505 Actions
.AddInitializerToDecl(OmpPrivParm
, Initializer
.get(),
506 /*DirectInit=*/true);
508 } else if (getLangOpts().CPlusPlus11
&& Tok
.is(tok::l_brace
)) {
509 // Parse C++0x braced-init-list.
510 Diag(Tok
, diag::warn_cxx98_compat_generalized_initializer_lists
);
512 ExprResult
Init(ParseBraceInitializer());
514 if (Init
.isInvalid()) {
515 Actions
.ActOnInitializerError(OmpPrivParm
);
517 Actions
.AddInitializerToDecl(OmpPrivParm
, Init
.get(),
518 /*DirectInit=*/true);
521 Actions
.ActOnUninitializedDecl(OmpPrivParm
);
525 /// Parses 'omp declare mapper' directive.
527 /// declare-mapper-directive:
528 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
529 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
530 /// annot_pragma_openmp_end
531 /// <mapper-identifier> and <var> are base language identifiers.
533 Parser::DeclGroupPtrTy
534 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS
) {
535 bool IsCorrect
= true;
537 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
538 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
539 getOpenMPDirectiveName(OMPD_declare_mapper
).data())) {
540 SkipUntil(tok::annot_pragma_openmp_end
, StopBeforeMatch
);
541 return DeclGroupPtrTy();
544 // Parse <mapper-identifier>
545 auto &DeclNames
= Actions
.getASTContext().DeclarationNames
;
546 DeclarationName MapperId
;
547 if (PP
.LookAhead(0).is(tok::colon
)) {
548 if (Tok
.isNot(tok::identifier
) && Tok
.isNot(tok::kw_default
)) {
549 Diag(Tok
.getLocation(), diag::err_omp_mapper_illegal_identifier
);
552 MapperId
= DeclNames
.getIdentifier(Tok
.getIdentifierInfo());
556 ExpectAndConsume(tok::colon
);
558 // If no mapper identifier is provided, its name is "default" by default
560 DeclNames
.getIdentifier(&Actions
.getASTContext().Idents
.get("default"));
563 if (!IsCorrect
&& Tok
.is(tok::annot_pragma_openmp_end
))
564 return DeclGroupPtrTy();
566 // Parse <type> <var>
567 DeclarationName VName
;
570 TypeResult ParsedType
= parseOpenMPDeclareMapperVarDecl(Range
, VName
, AS
);
571 if (ParsedType
.isUsable())
573 Actions
.ActOnOpenMPDeclareMapperType(Range
.getBegin(), ParsedType
);
574 if (MapperType
.isNull())
577 SkipUntil(tok::annot_pragma_openmp_end
, Parser::StopBeforeMatch
);
578 return DeclGroupPtrTy();
582 IsCorrect
&= !T
.consumeClose();
584 SkipUntil(tok::annot_pragma_openmp_end
, Parser::StopBeforeMatch
);
585 return DeclGroupPtrTy();
589 DeclarationNameInfo DirName
;
590 SourceLocation Loc
= Tok
.getLocation();
591 unsigned ScopeFlags
= Scope::FnScope
| Scope::DeclScope
|
592 Scope::CompoundStmtScope
| Scope::OpenMPDirectiveScope
;
593 ParseScope
OMPDirectiveScope(this, ScopeFlags
);
594 Actions
.StartOpenMPDSABlock(OMPD_declare_mapper
, DirName
, getCurScope(), Loc
);
596 // Add the mapper variable declaration.
597 ExprResult MapperVarRef
= Actions
.ActOnOpenMPDeclareMapperDirectiveVarDecl(
598 getCurScope(), MapperType
, Range
.getBegin(), VName
);
600 // Parse map clauses.
601 SmallVector
<OMPClause
*, 6> Clauses
;
602 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
603 OpenMPClauseKind CKind
= Tok
.isAnnotation()
605 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
606 Actions
.StartOpenMPClause(CKind
);
608 ParseOpenMPClause(OMPD_declare_mapper
, CKind
, Clauses
.empty());
610 Clauses
.push_back(Clause
);
614 if (Tok
.is(tok::comma
))
616 Actions
.EndOpenMPClause();
618 if (Clauses
.empty()) {
619 Diag(Tok
, diag::err_omp_expected_clause
)
620 << getOpenMPDirectiveName(OMPD_declare_mapper
);
625 Actions
.EndOpenMPDSABlock(nullptr);
626 OMPDirectiveScope
.Exit();
627 DeclGroupPtrTy DG
= Actions
.ActOnOpenMPDeclareMapperDirective(
628 getCurScope(), Actions
.getCurLexicalContext(), MapperId
, MapperType
,
629 Range
.getBegin(), VName
, AS
, MapperVarRef
.get(), Clauses
);
631 return DeclGroupPtrTy();
636 TypeResult
Parser::parseOpenMPDeclareMapperVarDecl(SourceRange
&Range
,
637 DeclarationName
&Name
,
638 AccessSpecifier AS
) {
639 // Parse the common declaration-specifiers piece.
640 Parser::DeclSpecContext DSC
= Parser::DeclSpecContext::DSC_type_specifier
;
641 DeclSpec
DS(AttrFactory
);
642 ParseSpecifierQualifierList(DS
, AS
, DSC
);
644 // Parse the declarator.
645 DeclaratorContext Context
= DeclaratorContext::Prototype
;
646 Declarator
DeclaratorInfo(DS
, ParsedAttributesView::none(), Context
);
647 ParseDeclarator(DeclaratorInfo
);
648 Range
= DeclaratorInfo
.getSourceRange();
649 if (DeclaratorInfo
.getIdentifier() == nullptr) {
650 Diag(Tok
.getLocation(), diag::err_omp_mapper_expected_declarator
);
653 Name
= Actions
.GetNameForDeclarator(DeclaratorInfo
).getName();
655 return Actions
.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo
);
659 /// RAII that recreates function context for correct parsing of clauses of
660 /// 'declare simd' construct.
661 /// OpenMP, 2.8.2 declare simd Construct
662 /// The expressions appearing in the clauses of this directive are evaluated in
663 /// the scope of the arguments of the function declaration or definition.
664 class FNContextRAII final
{
666 Sema::CXXThisScopeRAII
*ThisScope
;
667 Parser::MultiParseScope Scopes
;
668 bool HasFunScope
= false;
669 FNContextRAII() = delete;
670 FNContextRAII(const FNContextRAII
&) = delete;
671 FNContextRAII
&operator=(const FNContextRAII
&) = delete;
674 FNContextRAII(Parser
&P
, Parser::DeclGroupPtrTy Ptr
) : P(P
), Scopes(P
) {
675 Decl
*D
= *Ptr
.get().begin();
676 NamedDecl
*ND
= dyn_cast
<NamedDecl
>(D
);
677 RecordDecl
*RD
= dyn_cast_or_null
<RecordDecl
>(D
->getDeclContext());
678 Sema
&Actions
= P
.getActions();
680 // Allow 'this' within late-parsed attributes.
681 ThisScope
= new Sema::CXXThisScopeRAII(Actions
, RD
, Qualifiers(),
682 ND
&& ND
->isCXXInstanceMember());
684 // If the Decl is templatized, add template parameters to scope.
685 // FIXME: Track CurTemplateDepth?
686 P
.ReenterTemplateScopes(Scopes
, D
);
688 // If the Decl is on a function, add function parameters to the scope.
689 if (D
->isFunctionOrFunctionTemplate()) {
691 Scopes
.Enter(Scope::FnScope
| Scope::DeclScope
|
692 Scope::CompoundStmtScope
);
693 Actions
.ActOnReenterFunctionContext(Actions
.getCurScope(), D
);
698 P
.getActions().ActOnExitFunctionContext();
704 /// Parses clauses for 'declare simd' directive.
706 /// 'inbranch' | 'notinbranch'
707 /// 'simdlen' '(' <expr> ')'
708 /// { 'uniform' '(' <argument_list> ')' }
709 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
710 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
711 static bool parseDeclareSimdClauses(
712 Parser
&P
, OMPDeclareSimdDeclAttr::BranchStateTy
&BS
, ExprResult
&SimdLen
,
713 SmallVectorImpl
<Expr
*> &Uniforms
, SmallVectorImpl
<Expr
*> &Aligneds
,
714 SmallVectorImpl
<Expr
*> &Alignments
, SmallVectorImpl
<Expr
*> &Linears
,
715 SmallVectorImpl
<unsigned> &LinModifiers
, SmallVectorImpl
<Expr
*> &Steps
) {
717 const Token
&Tok
= P
.getCurToken();
718 bool IsError
= false;
719 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
720 if (Tok
.isNot(tok::identifier
))
722 OMPDeclareSimdDeclAttr::BranchStateTy Out
;
723 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
724 StringRef ClauseName
= II
->getName();
725 // Parse 'inranch|notinbranch' clauses.
726 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName
, Out
)) {
727 if (BS
!= OMPDeclareSimdDeclAttr::BS_Undefined
&& BS
!= Out
) {
728 P
.Diag(Tok
, diag::err_omp_declare_simd_inbranch_notinbranch
)
730 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS
) << BSRange
;
734 BSRange
= SourceRange(Tok
.getLocation(), Tok
.getEndLoc());
736 } else if (ClauseName
.equals("simdlen")) {
737 if (SimdLen
.isUsable()) {
738 P
.Diag(Tok
, diag::err_omp_more_one_clause
)
739 << getOpenMPDirectiveName(OMPD_declare_simd
) << ClauseName
<< 0;
744 SimdLen
= P
.ParseOpenMPParensExpr(ClauseName
, RLoc
);
745 if (SimdLen
.isInvalid())
748 OpenMPClauseKind CKind
= getOpenMPClauseKind(ClauseName
);
749 if (CKind
== OMPC_uniform
|| CKind
== OMPC_aligned
||
750 CKind
== OMPC_linear
) {
751 Sema::OpenMPVarListDataTy Data
;
752 SmallVectorImpl
<Expr
*> *Vars
= &Uniforms
;
753 if (CKind
== OMPC_aligned
) {
755 } else if (CKind
== OMPC_linear
) {
756 Data
.ExtraModifier
= OMPC_LINEAR_val
;
761 if (P
.ParseOpenMPVarList(OMPD_declare_simd
,
762 getOpenMPClauseKind(ClauseName
), *Vars
, Data
))
764 if (CKind
== OMPC_aligned
) {
765 Alignments
.append(Aligneds
.size() - Alignments
.size(),
766 Data
.DepModOrTailExpr
);
767 } else if (CKind
== OMPC_linear
) {
768 assert(0 <= Data
.ExtraModifier
&&
769 Data
.ExtraModifier
<= OMPC_LINEAR_unknown
&&
770 "Unexpected linear modifier.");
771 if (P
.getActions().CheckOpenMPLinearModifier(
772 static_cast<OpenMPLinearClauseKind
>(Data
.ExtraModifier
),
773 Data
.ExtraModifierLoc
))
774 Data
.ExtraModifier
= OMPC_LINEAR_val
;
775 LinModifiers
.append(Linears
.size() - LinModifiers
.size(),
777 Steps
.append(Linears
.size() - Steps
.size(), Data
.DepModOrTailExpr
);
780 // TODO: add parsing of other clauses.
784 if (Tok
.is(tok::comma
))
790 /// Parse clauses for '#pragma omp declare simd'.
791 Parser::DeclGroupPtrTy
792 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr
,
793 CachedTokens
&Toks
, SourceLocation Loc
) {
794 PP
.EnterToken(Tok
, /*IsReinject*/ true);
795 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
796 /*IsReinject*/ true);
797 // Consume the previously pushed token.
798 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
799 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
801 FNContextRAII
FnContext(*this, Ptr
);
802 OMPDeclareSimdDeclAttr::BranchStateTy BS
=
803 OMPDeclareSimdDeclAttr::BS_Undefined
;
805 SmallVector
<Expr
*, 4> Uniforms
;
806 SmallVector
<Expr
*, 4> Aligneds
;
807 SmallVector
<Expr
*, 4> Alignments
;
808 SmallVector
<Expr
*, 4> Linears
;
809 SmallVector
<unsigned, 4> LinModifiers
;
810 SmallVector
<Expr
*, 4> Steps
;
812 parseDeclareSimdClauses(*this, BS
, Simdlen
, Uniforms
, Aligneds
,
813 Alignments
, Linears
, LinModifiers
, Steps
);
814 skipUntilPragmaOpenMPEnd(OMPD_declare_simd
);
815 // Skip the last annot_pragma_openmp_end.
816 SourceLocation EndLoc
= ConsumeAnnotationToken();
819 return Actions
.ActOnOpenMPDeclareSimdDirective(
820 Ptr
, BS
, Simdlen
.get(), Uniforms
, Aligneds
, Alignments
, Linears
,
821 LinModifiers
, Steps
, SourceRange(Loc
, EndLoc
));
825 /// Constant used in the diagnostics to distinguish the levels in an OpenMP
826 /// contexts: selector-set={selector(trait, ...), ...}, ....
828 CONTEXT_SELECTOR_SET_LVL
= 0,
829 CONTEXT_SELECTOR_LVL
= 1,
830 CONTEXT_TRAIT_LVL
= 2,
833 static StringRef
stringLiteralParser(Parser
&P
) {
834 ExprResult Res
= P
.ParseStringLiteralExpression(true);
835 return Res
.isUsable() ? Res
.getAs
<StringLiteral
>()->getString() : "";
838 static StringRef
getNameFromIdOrString(Parser
&P
, Token
&Tok
,
840 if (Tok
.is(tok::identifier
) || Tok
.is(tok::kw_for
)) {
841 llvm::SmallString
<16> Buffer
;
842 StringRef Name
= P
.getPreprocessor().getSpelling(Tok
, Buffer
);
843 (void)P
.ConsumeToken();
847 if (tok::isStringLiteral(Tok
.getKind()))
848 return stringLiteralParser(P
);
850 P
.Diag(Tok
.getLocation(),
851 diag::warn_omp_declare_variant_string_literal_or_identifier
)
856 static bool checkForDuplicates(Parser
&P
, StringRef Name
,
857 SourceLocation NameLoc
,
858 llvm::StringMap
<SourceLocation
> &Seen
,
860 auto Res
= Seen
.try_emplace(Name
, NameLoc
);
864 // Each trait-set-selector-name, trait-selector-name and trait-name can
865 // only be specified once.
866 P
.Diag(NameLoc
, diag::warn_omp_declare_variant_ctx_mutiple_use
)
868 P
.Diag(Res
.first
->getValue(), diag::note_omp_declare_variant_ctx_used_here
)
874 void Parser::parseOMPTraitPropertyKind(OMPTraitProperty
&TIProperty
,
875 llvm::omp::TraitSet Set
,
876 llvm::omp::TraitSelector Selector
,
877 llvm::StringMap
<SourceLocation
> &Seen
) {
878 TIProperty
.Kind
= TraitProperty::invalid
;
880 SourceLocation NameLoc
= Tok
.getLocation();
881 StringRef Name
= getNameFromIdOrString(*this, Tok
, CONTEXT_TRAIT_LVL
);
883 Diag(Tok
.getLocation(), diag::note_omp_declare_variant_ctx_options
)
884 << CONTEXT_TRAIT_LVL
<< listOpenMPContextTraitProperties(Set
, Selector
);
888 TIProperty
.RawString
= Name
;
889 TIProperty
.Kind
= getOpenMPContextTraitPropertyKind(Set
, Selector
, Name
);
890 if (TIProperty
.Kind
!= TraitProperty::invalid
) {
891 if (checkForDuplicates(*this, Name
, NameLoc
, Seen
, CONTEXT_TRAIT_LVL
))
892 TIProperty
.Kind
= TraitProperty::invalid
;
896 // It follows diagnosis and helping notes.
897 // FIXME: We should move the diagnosis string generation into libFrontend.
898 Diag(NameLoc
, diag::warn_omp_declare_variant_ctx_not_a_property
)
899 << Name
<< getOpenMPContextTraitSelectorName(Selector
)
900 << getOpenMPContextTraitSetName(Set
);
902 TraitSet SetForName
= getOpenMPContextTraitSetKind(Name
);
903 if (SetForName
!= TraitSet::invalid
) {
904 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_is_a
)
905 << Name
<< CONTEXT_SELECTOR_SET_LVL
<< CONTEXT_TRAIT_LVL
;
906 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_try
)
907 << Name
<< "<selector-name>"
908 << "(<property-name>)";
911 TraitSelector SelectorForName
= getOpenMPContextTraitSelectorKind(Name
);
912 if (SelectorForName
!= TraitSelector::invalid
) {
913 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_is_a
)
914 << Name
<< CONTEXT_SELECTOR_LVL
<< CONTEXT_TRAIT_LVL
;
915 bool AllowsTraitScore
= false;
916 bool RequiresProperty
= false;
917 isValidTraitSelectorForTraitSet(
918 SelectorForName
, getOpenMPContextTraitSetForSelector(SelectorForName
),
919 AllowsTraitScore
, RequiresProperty
);
920 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_try
)
921 << getOpenMPContextTraitSetName(
922 getOpenMPContextTraitSetForSelector(SelectorForName
))
923 << Name
<< (RequiresProperty
? "(<property-name>)" : "");
926 for (const auto &PotentialSet
:
927 {TraitSet::construct
, TraitSet::user
, TraitSet::implementation
,
929 TraitProperty PropertyForName
=
930 getOpenMPContextTraitPropertyKind(PotentialSet
, Selector
, Name
);
931 if (PropertyForName
== TraitProperty::invalid
)
933 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_try
)
934 << getOpenMPContextTraitSetName(
935 getOpenMPContextTraitSetForProperty(PropertyForName
))
936 << getOpenMPContextTraitSelectorName(
937 getOpenMPContextTraitSelectorForProperty(PropertyForName
))
938 << ("(" + Name
+ ")").str();
941 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_options
)
942 << CONTEXT_TRAIT_LVL
<< listOpenMPContextTraitProperties(Set
, Selector
);
945 static bool checkExtensionProperty(Parser
&P
, SourceLocation Loc
,
946 OMPTraitProperty
&TIProperty
,
947 OMPTraitSelector
&TISelector
,
948 llvm::StringMap
<SourceLocation
> &Seen
) {
949 assert(TISelector
.Kind
==
950 llvm::omp::TraitSelector::implementation_extension
&&
951 "Only for extension properties, e.g., "
952 "`implementation={extension(PROPERTY)}`");
953 if (TIProperty
.Kind
== TraitProperty::invalid
)
956 if (TIProperty
.Kind
==
957 TraitProperty::implementation_extension_disable_implicit_base
)
960 if (TIProperty
.Kind
==
961 TraitProperty::implementation_extension_allow_templates
)
964 if (TIProperty
.Kind
==
965 TraitProperty::implementation_extension_bind_to_declaration
)
968 auto IsMatchExtension
= [](OMPTraitProperty
&TP
) {
970 llvm::omp::TraitProperty::implementation_extension_match_all
||
972 llvm::omp::TraitProperty::implementation_extension_match_any
||
974 llvm::omp::TraitProperty::implementation_extension_match_none
);
977 if (IsMatchExtension(TIProperty
)) {
978 for (OMPTraitProperty
&SeenProp
: TISelector
.Properties
)
979 if (IsMatchExtension(SeenProp
)) {
980 P
.Diag(Loc
, diag::err_omp_variant_ctx_second_match_extension
);
981 StringRef SeenName
= llvm::omp::getOpenMPContextTraitPropertyName(
982 SeenProp
.Kind
, SeenProp
.RawString
);
983 SourceLocation SeenLoc
= Seen
[SeenName
];
984 P
.Diag(SeenLoc
, diag::note_omp_declare_variant_ctx_used_here
)
985 << CONTEXT_TRAIT_LVL
<< SeenName
;
991 llvm_unreachable("Unknown extension property!");
994 void Parser::parseOMPContextProperty(OMPTraitSelector
&TISelector
,
995 llvm::omp::TraitSet Set
,
996 llvm::StringMap
<SourceLocation
> &Seen
) {
997 assert(TISelector
.Kind
!= TraitSelector::user_condition
&&
998 "User conditions are special properties not handled here!");
1000 SourceLocation PropertyLoc
= Tok
.getLocation();
1001 OMPTraitProperty TIProperty
;
1002 parseOMPTraitPropertyKind(TIProperty
, Set
, TISelector
.Kind
, Seen
);
1004 if (TISelector
.Kind
== llvm::omp::TraitSelector::implementation_extension
)
1005 if (!checkExtensionProperty(*this, Tok
.getLocation(), TIProperty
,
1007 TIProperty
.Kind
= TraitProperty::invalid
;
1009 // If we have an invalid property here we already issued a warning.
1010 if (TIProperty
.Kind
== TraitProperty::invalid
) {
1011 if (PropertyLoc
!= Tok
.getLocation())
1012 Diag(Tok
.getLocation(), diag::note_omp_declare_variant_ctx_continue_here
)
1013 << CONTEXT_TRAIT_LVL
;
1017 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty
.Kind
,
1018 TISelector
.Kind
, Set
)) {
1020 // If we make it here the property, selector, set, score, condition, ... are
1021 // all valid (or have been corrected). Thus we can record the property.
1022 TISelector
.Properties
.push_back(TIProperty
);
1026 Diag(PropertyLoc
, diag::warn_omp_ctx_incompatible_property_for_selector
)
1027 << getOpenMPContextTraitPropertyName(TIProperty
.Kind
,
1028 TIProperty
.RawString
)
1029 << getOpenMPContextTraitSelectorName(TISelector
.Kind
)
1030 << getOpenMPContextTraitSetName(Set
);
1031 Diag(PropertyLoc
, diag::note_omp_ctx_compatible_set_and_selector_for_property
)
1032 << getOpenMPContextTraitPropertyName(TIProperty
.Kind
,
1033 TIProperty
.RawString
)
1034 << getOpenMPContextTraitSelectorName(
1035 getOpenMPContextTraitSelectorForProperty(TIProperty
.Kind
))
1036 << getOpenMPContextTraitSetName(
1037 getOpenMPContextTraitSetForProperty(TIProperty
.Kind
));
1038 Diag(Tok
.getLocation(), diag::note_omp_declare_variant_ctx_continue_here
)
1039 << CONTEXT_TRAIT_LVL
;
1042 void Parser::parseOMPTraitSelectorKind(OMPTraitSelector
&TISelector
,
1043 llvm::omp::TraitSet Set
,
1044 llvm::StringMap
<SourceLocation
> &Seen
) {
1045 TISelector
.Kind
= TraitSelector::invalid
;
1047 SourceLocation NameLoc
= Tok
.getLocation();
1048 StringRef Name
= getNameFromIdOrString(*this, Tok
, CONTEXT_SELECTOR_LVL
);
1050 Diag(Tok
.getLocation(), diag::note_omp_declare_variant_ctx_options
)
1051 << CONTEXT_SELECTOR_LVL
<< listOpenMPContextTraitSelectors(Set
);
1055 TISelector
.Kind
= getOpenMPContextTraitSelectorKind(Name
);
1056 if (TISelector
.Kind
!= TraitSelector::invalid
) {
1057 if (checkForDuplicates(*this, Name
, NameLoc
, Seen
, CONTEXT_SELECTOR_LVL
))
1058 TISelector
.Kind
= TraitSelector::invalid
;
1062 // It follows diagnosis and helping notes.
1063 Diag(NameLoc
, diag::warn_omp_declare_variant_ctx_not_a_selector
)
1064 << Name
<< getOpenMPContextTraitSetName(Set
);
1066 TraitSet SetForName
= getOpenMPContextTraitSetKind(Name
);
1067 if (SetForName
!= TraitSet::invalid
) {
1068 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_is_a
)
1069 << Name
<< CONTEXT_SELECTOR_SET_LVL
<< CONTEXT_SELECTOR_LVL
;
1070 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_try
)
1071 << Name
<< "<selector-name>"
1072 << "<property-name>";
1075 for (const auto &PotentialSet
:
1076 {TraitSet::construct
, TraitSet::user
, TraitSet::implementation
,
1077 TraitSet::device
}) {
1078 TraitProperty PropertyForName
= getOpenMPContextTraitPropertyKind(
1079 PotentialSet
, TraitSelector::invalid
, Name
);
1080 if (PropertyForName
== TraitProperty::invalid
)
1082 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_is_a
)
1083 << Name
<< CONTEXT_TRAIT_LVL
<< CONTEXT_SELECTOR_LVL
;
1084 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_try
)
1085 << getOpenMPContextTraitSetName(
1086 getOpenMPContextTraitSetForProperty(PropertyForName
))
1087 << getOpenMPContextTraitSelectorName(
1088 getOpenMPContextTraitSelectorForProperty(PropertyForName
))
1089 << ("(" + Name
+ ")").str();
1092 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_options
)
1093 << CONTEXT_SELECTOR_LVL
<< listOpenMPContextTraitSelectors(Set
);
1096 /// Parse optional 'score' '(' <expr> ')' ':'.
1097 static ExprResult
parseContextScore(Parser
&P
) {
1098 ExprResult ScoreExpr
;
1099 llvm::SmallString
<16> Buffer
;
1100 StringRef SelectorName
=
1101 P
.getPreprocessor().getSpelling(P
.getCurToken(), Buffer
);
1102 if (!SelectorName
.equals("score"))
1104 (void)P
.ConsumeToken();
1105 SourceLocation RLoc
;
1106 ScoreExpr
= P
.ParseOpenMPParensExpr(SelectorName
, RLoc
);
1108 if (P
.getCurToken().is(tok::colon
))
1109 (void)P
.ConsumeAnyToken();
1111 P
.Diag(P
.getCurToken(), diag::warn_omp_declare_variant_expected
)
1113 << "score expression";
1117 /// Parses an OpenMP context selector.
1119 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
1120 void Parser::parseOMPContextSelector(
1121 OMPTraitSelector
&TISelector
, llvm::omp::TraitSet Set
,
1122 llvm::StringMap
<SourceLocation
> &SeenSelectors
) {
1123 unsigned short OuterPC
= ParenCount
;
1125 // If anything went wrong we issue an error or warning and then skip the rest
1126 // of the selector. However, commas are ambiguous so we look for the nesting
1127 // of parentheses here as well.
1128 auto FinishSelector
= [OuterPC
, this]() -> void {
1131 while (!SkipUntil({tok::r_brace
, tok::r_paren
, tok::comma
,
1132 tok::annot_pragma_openmp_end
},
1135 if (Tok
.is(tok::r_paren
) && OuterPC
> ParenCount
)
1136 (void)ConsumeParen();
1137 if (OuterPC
<= ParenCount
) {
1141 if (!Tok
.is(tok::comma
) && !Tok
.is(tok::r_paren
)) {
1145 (void)ConsumeAnyToken();
1147 Diag(Tok
.getLocation(), diag::note_omp_declare_variant_ctx_continue_here
)
1148 << CONTEXT_SELECTOR_LVL
;
1151 SourceLocation SelectorLoc
= Tok
.getLocation();
1152 parseOMPTraitSelectorKind(TISelector
, Set
, SeenSelectors
);
1153 if (TISelector
.Kind
== TraitSelector::invalid
)
1154 return FinishSelector();
1156 bool AllowsTraitScore
= false;
1157 bool RequiresProperty
= false;
1158 if (!isValidTraitSelectorForTraitSet(TISelector
.Kind
, Set
, AllowsTraitScore
,
1159 RequiresProperty
)) {
1160 Diag(SelectorLoc
, diag::warn_omp_ctx_incompatible_selector_for_set
)
1161 << getOpenMPContextTraitSelectorName(TISelector
.Kind
)
1162 << getOpenMPContextTraitSetName(Set
);
1163 Diag(SelectorLoc
, diag::note_omp_ctx_compatible_set_for_selector
)
1164 << getOpenMPContextTraitSelectorName(TISelector
.Kind
)
1165 << getOpenMPContextTraitSetName(
1166 getOpenMPContextTraitSetForSelector(TISelector
.Kind
))
1167 << RequiresProperty
;
1168 return FinishSelector();
1171 if (!RequiresProperty
) {
1172 TISelector
.Properties
.push_back(
1173 {getOpenMPContextTraitPropertyForSelector(TISelector
.Kind
),
1174 getOpenMPContextTraitSelectorName(TISelector
.Kind
)});
1178 if (!Tok
.is(tok::l_paren
)) {
1179 Diag(SelectorLoc
, diag::warn_omp_ctx_selector_without_properties
)
1180 << getOpenMPContextTraitSelectorName(TISelector
.Kind
)
1181 << getOpenMPContextTraitSetName(Set
);
1182 return FinishSelector();
1185 if (TISelector
.Kind
== TraitSelector::user_condition
) {
1186 SourceLocation RLoc
;
1187 ExprResult Condition
= ParseOpenMPParensExpr("user condition", RLoc
);
1188 if (!Condition
.isUsable())
1189 return FinishSelector();
1190 TISelector
.ScoreOrCondition
= Condition
.get();
1191 TISelector
.Properties
.push_back(
1192 {TraitProperty::user_condition_unknown
, "<condition>"});
1196 BalancedDelimiterTracker
BDT(*this, tok::l_paren
,
1197 tok::annot_pragma_openmp_end
);
1199 (void)BDT
.consumeOpen();
1201 SourceLocation ScoreLoc
= Tok
.getLocation();
1202 ExprResult Score
= parseContextScore(*this);
1204 if (!AllowsTraitScore
&& !Score
.isUnset()) {
1205 if (Score
.isUsable()) {
1206 Diag(ScoreLoc
, diag::warn_omp_ctx_incompatible_score_for_property
)
1207 << getOpenMPContextTraitSelectorName(TISelector
.Kind
)
1208 << getOpenMPContextTraitSetName(Set
) << Score
.get();
1210 Diag(ScoreLoc
, diag::warn_omp_ctx_incompatible_score_for_property
)
1211 << getOpenMPContextTraitSelectorName(TISelector
.Kind
)
1212 << getOpenMPContextTraitSetName(Set
) << "<invalid>";
1214 Score
= ExprResult();
1217 if (Score
.isUsable())
1218 TISelector
.ScoreOrCondition
= Score
.get();
1220 llvm::StringMap
<SourceLocation
> SeenProperties
;
1222 parseOMPContextProperty(TISelector
, Set
, SeenProperties
);
1223 } while (TryConsumeToken(tok::comma
));
1229 void Parser::parseOMPTraitSetKind(OMPTraitSet
&TISet
,
1230 llvm::StringMap
<SourceLocation
> &Seen
) {
1231 TISet
.Kind
= TraitSet::invalid
;
1233 SourceLocation NameLoc
= Tok
.getLocation();
1234 StringRef Name
= getNameFromIdOrString(*this, Tok
, CONTEXT_SELECTOR_SET_LVL
);
1236 Diag(Tok
.getLocation(), diag::note_omp_declare_variant_ctx_options
)
1237 << CONTEXT_SELECTOR_SET_LVL
<< listOpenMPContextTraitSets();
1241 TISet
.Kind
= getOpenMPContextTraitSetKind(Name
);
1242 if (TISet
.Kind
!= TraitSet::invalid
) {
1243 if (checkForDuplicates(*this, Name
, NameLoc
, Seen
,
1244 CONTEXT_SELECTOR_SET_LVL
))
1245 TISet
.Kind
= TraitSet::invalid
;
1249 // It follows diagnosis and helping notes.
1250 Diag(NameLoc
, diag::warn_omp_declare_variant_ctx_not_a_set
) << Name
;
1252 TraitSelector SelectorForName
= getOpenMPContextTraitSelectorKind(Name
);
1253 if (SelectorForName
!= TraitSelector::invalid
) {
1254 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_is_a
)
1255 << Name
<< CONTEXT_SELECTOR_LVL
<< CONTEXT_SELECTOR_SET_LVL
;
1256 bool AllowsTraitScore
= false;
1257 bool RequiresProperty
= false;
1258 isValidTraitSelectorForTraitSet(
1259 SelectorForName
, getOpenMPContextTraitSetForSelector(SelectorForName
),
1260 AllowsTraitScore
, RequiresProperty
);
1261 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_try
)
1262 << getOpenMPContextTraitSetName(
1263 getOpenMPContextTraitSetForSelector(SelectorForName
))
1264 << Name
<< (RequiresProperty
? "(<property-name>)" : "");
1267 for (const auto &PotentialSet
:
1268 {TraitSet::construct
, TraitSet::user
, TraitSet::implementation
,
1269 TraitSet::device
}) {
1270 TraitProperty PropertyForName
= getOpenMPContextTraitPropertyKind(
1271 PotentialSet
, TraitSelector::invalid
, Name
);
1272 if (PropertyForName
== TraitProperty::invalid
)
1274 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_is_a
)
1275 << Name
<< CONTEXT_TRAIT_LVL
<< CONTEXT_SELECTOR_SET_LVL
;
1276 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_try
)
1277 << getOpenMPContextTraitSetName(
1278 getOpenMPContextTraitSetForProperty(PropertyForName
))
1279 << getOpenMPContextTraitSelectorName(
1280 getOpenMPContextTraitSelectorForProperty(PropertyForName
))
1281 << ("(" + Name
+ ")").str();
1284 Diag(NameLoc
, diag::note_omp_declare_variant_ctx_options
)
1285 << CONTEXT_SELECTOR_SET_LVL
<< listOpenMPContextTraitSets();
1288 /// Parses an OpenMP context selector set.
1290 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
1291 void Parser::parseOMPContextSelectorSet(
1292 OMPTraitSet
&TISet
, llvm::StringMap
<SourceLocation
> &SeenSets
) {
1293 auto OuterBC
= BraceCount
;
1295 // If anything went wrong we issue an error or warning and then skip the rest
1296 // of the set. However, commas are ambiguous so we look for the nesting
1297 // of braces here as well.
1298 auto FinishSelectorSet
= [this, OuterBC
]() -> void {
1301 while (!SkipUntil({tok::comma
, tok::r_brace
, tok::r_paren
,
1302 tok::annot_pragma_openmp_end
},
1305 if (Tok
.is(tok::r_brace
) && OuterBC
> BraceCount
)
1306 (void)ConsumeBrace();
1307 if (OuterBC
<= BraceCount
) {
1311 if (!Tok
.is(tok::comma
) && !Tok
.is(tok::r_brace
)) {
1315 (void)ConsumeAnyToken();
1317 Diag(Tok
.getLocation(), diag::note_omp_declare_variant_ctx_continue_here
)
1318 << CONTEXT_SELECTOR_SET_LVL
;
1321 parseOMPTraitSetKind(TISet
, SeenSets
);
1322 if (TISet
.Kind
== TraitSet::invalid
)
1323 return FinishSelectorSet();
1326 if (!TryConsumeToken(tok::equal
))
1327 Diag(Tok
.getLocation(), diag::warn_omp_declare_variant_expected
)
1329 << ("context set name \"" + getOpenMPContextTraitSetName(TISet
.Kind
) +
1334 if (Tok
.is(tok::l_brace
)) {
1335 (void)ConsumeBrace();
1337 Diag(Tok
.getLocation(), diag::warn_omp_declare_variant_expected
)
1339 << ("'=' that follows the context set name \"" +
1340 getOpenMPContextTraitSetName(TISet
.Kind
) + "\"")
1344 llvm::StringMap
<SourceLocation
> SeenSelectors
;
1346 OMPTraitSelector TISelector
;
1347 parseOMPContextSelector(TISelector
, TISet
.Kind
, SeenSelectors
);
1348 if (TISelector
.Kind
!= TraitSelector::invalid
&&
1349 !TISelector
.Properties
.empty())
1350 TISet
.Selectors
.push_back(TISelector
);
1351 } while (TryConsumeToken(tok::comma
));
1354 if (Tok
.is(tok::r_brace
)) {
1355 (void)ConsumeBrace();
1357 Diag(Tok
.getLocation(), diag::warn_omp_declare_variant_expected
)
1359 << ("context selectors for the context set \"" +
1360 getOpenMPContextTraitSetName(TISet
.Kind
) + "\"")
1365 /// Parse OpenMP context selectors:
1367 /// <trait-set-selector> [, <trait-set-selector>]*
1368 bool Parser::parseOMPContextSelectors(SourceLocation Loc
, OMPTraitInfo
&TI
) {
1369 llvm::StringMap
<SourceLocation
> SeenSets
;
1372 parseOMPContextSelectorSet(TISet
, SeenSets
);
1373 if (TISet
.Kind
!= TraitSet::invalid
&& !TISet
.Selectors
.empty())
1374 TI
.Sets
.push_back(TISet
);
1375 } while (TryConsumeToken(tok::comma
));
1380 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
1381 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr
,
1383 SourceLocation Loc
) {
1384 PP
.EnterToken(Tok
, /*IsReinject*/ true);
1385 PP
.EnterTokenStream(Toks
, /*DisableMacroExpansion=*/true,
1386 /*IsReinject*/ true);
1387 // Consume the previously pushed token.
1388 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1389 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1391 FNContextRAII
FnContext(*this, Ptr
);
1392 // Parse function declaration id.
1393 SourceLocation RLoc
;
1394 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1395 // instead of MemberExprs.
1396 ExprResult AssociatedFunction
;
1398 // Do not mark function as is used to prevent its emission if this is the
1399 // only place where it is used.
1400 EnterExpressionEvaluationContext
Unevaluated(
1401 Actions
, Sema::ExpressionEvaluationContext::Unevaluated
);
1402 AssociatedFunction
= ParseOpenMPParensExpr(
1403 getOpenMPDirectiveName(OMPD_declare_variant
), RLoc
,
1404 /*IsAddressOfOperand=*/true);
1406 if (!AssociatedFunction
.isUsable()) {
1407 if (!Tok
.is(tok::annot_pragma_openmp_end
))
1408 while (!SkipUntil(tok::annot_pragma_openmp_end
, StopBeforeMatch
))
1410 // Skip the last annot_pragma_openmp_end.
1411 (void)ConsumeAnnotationToken();
1415 OMPTraitInfo
*ParentTI
= Actions
.getOMPTraitInfoForSurroundingScope();
1416 ASTContext
&ASTCtx
= Actions
.getASTContext();
1417 OMPTraitInfo
&TI
= ASTCtx
.getNewOMPTraitInfo();
1418 SmallVector
<Expr
*, 6> AdjustNothing
;
1419 SmallVector
<Expr
*, 6> AdjustNeedDevicePtr
;
1420 SmallVector
<OMPInteropInfo
, 3> AppendArgs
;
1421 SourceLocation AdjustArgsLoc
, AppendArgsLoc
;
1423 // At least one clause is required.
1424 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
1425 Diag(Tok
.getLocation(), diag::err_omp_declare_variant_wrong_clause
)
1426 << (getLangOpts().OpenMP
< 51 ? 0 : 1);
1429 bool IsError
= false;
1430 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
1431 OpenMPClauseKind CKind
= Tok
.isAnnotation()
1433 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
1434 if (!isAllowedClauseForDirective(OMPD_declare_variant
, CKind
,
1435 getLangOpts().OpenMP
)) {
1436 Diag(Tok
.getLocation(), diag::err_omp_declare_variant_wrong_clause
)
1437 << (getLangOpts().OpenMP
< 51 ? 0 : 1);
1443 IsError
= parseOMPDeclareVariantMatchClause(Loc
, TI
, ParentTI
);
1445 case OMPC_adjust_args
: {
1446 AdjustArgsLoc
= Tok
.getLocation();
1448 Sema::OpenMPVarListDataTy Data
;
1449 SmallVector
<Expr
*> Vars
;
1450 IsError
= ParseOpenMPVarList(OMPD_declare_variant
, OMPC_adjust_args
,
1453 llvm::append_range(Data
.ExtraModifier
== OMPC_ADJUST_ARGS_nothing
1455 : AdjustNeedDevicePtr
,
1459 case OMPC_append_args
:
1460 if (!AppendArgs
.empty()) {
1461 Diag(AppendArgsLoc
, diag::err_omp_more_one_clause
)
1462 << getOpenMPDirectiveName(OMPD_declare_variant
)
1463 << getOpenMPClauseName(CKind
) << 0;
1467 AppendArgsLoc
= Tok
.getLocation();
1469 IsError
= parseOpenMPAppendArgs(AppendArgs
);
1473 llvm_unreachable("Unexpected clause for declare variant.");
1477 while (!SkipUntil(tok::annot_pragma_openmp_end
, StopBeforeMatch
))
1479 // Skip the last annot_pragma_openmp_end.
1480 (void)ConsumeAnnotationToken();
1484 if (Tok
.is(tok::comma
))
1488 std::optional
<std::pair
<FunctionDecl
*, Expr
*>> DeclVarData
=
1489 Actions
.checkOpenMPDeclareVariantFunction(
1490 Ptr
, AssociatedFunction
.get(), TI
, AppendArgs
.size(),
1491 SourceRange(Loc
, Tok
.getLocation()));
1493 if (DeclVarData
&& !TI
.Sets
.empty())
1494 Actions
.ActOnOpenMPDeclareVariantDirective(
1495 DeclVarData
->first
, DeclVarData
->second
, TI
, AdjustNothing
,
1496 AdjustNeedDevicePtr
, AppendArgs
, AdjustArgsLoc
, AppendArgsLoc
,
1497 SourceRange(Loc
, Tok
.getLocation()));
1499 // Skip the last annot_pragma_openmp_end.
1500 (void)ConsumeAnnotationToken();
1503 bool Parser::parseOpenMPAppendArgs(
1504 SmallVectorImpl
<OMPInteropInfo
> &InteropInfos
) {
1505 bool HasError
= false;
1507 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
1508 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
1509 getOpenMPClauseName(OMPC_append_args
).data()))
1512 // Parse the list of append-ops, each is;
1513 // interop(interop-type[,interop-type]...)
1514 while (Tok
.is(tok::identifier
) && Tok
.getIdentifierInfo()->isStr("interop")) {
1516 BalancedDelimiterTracker
IT(*this, tok::l_paren
,
1517 tok::annot_pragma_openmp_end
);
1518 if (IT
.expectAndConsume(diag::err_expected_lparen_after
, "interop"))
1521 OMPInteropInfo InteropInfo
;
1522 if (ParseOMPInteropInfo(InteropInfo
, OMPC_append_args
))
1525 InteropInfos
.push_back(InteropInfo
);
1528 if (Tok
.is(tok::comma
))
1531 if (!HasError
&& InteropInfos
.empty()) {
1533 Diag(Tok
.getLocation(), diag::err_omp_unexpected_append_op
);
1534 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
1537 HasError
= T
.consumeClose() || HasError
;
1541 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc
,
1543 OMPTraitInfo
*ParentTI
) {
1545 OpenMPClauseKind CKind
= Tok
.isAnnotation()
1547 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
1548 if (CKind
!= OMPC_match
) {
1549 Diag(Tok
.getLocation(), diag::err_omp_declare_variant_wrong_clause
)
1550 << (getLangOpts().OpenMP
< 51 ? 0 : 1);
1553 (void)ConsumeToken();
1555 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
1556 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
1557 getOpenMPClauseName(OMPC_match
).data()))
1560 // Parse inner context selectors.
1561 parseOMPContextSelectors(Loc
, TI
);
1564 (void)T
.consumeClose();
1569 // Merge the parent/outer trait info into the one we just parsed and diagnose
1571 // TODO: Keep some source location in the TI to provide better diagnostics.
1572 // TODO: Perform some kind of equivalence check on the condition and score
1574 for (const OMPTraitSet
&ParentSet
: ParentTI
->Sets
) {
1575 bool MergedSet
= false;
1576 for (OMPTraitSet
&Set
: TI
.Sets
) {
1577 if (Set
.Kind
!= ParentSet
.Kind
)
1580 for (const OMPTraitSelector
&ParentSelector
: ParentSet
.Selectors
) {
1581 bool MergedSelector
= false;
1582 for (OMPTraitSelector
&Selector
: Set
.Selectors
) {
1583 if (Selector
.Kind
!= ParentSelector
.Kind
)
1585 MergedSelector
= true;
1586 for (const OMPTraitProperty
&ParentProperty
:
1587 ParentSelector
.Properties
) {
1588 bool MergedProperty
= false;
1589 for (OMPTraitProperty
&Property
: Selector
.Properties
) {
1590 // Ignore "equivalent" properties.
1591 if (Property
.Kind
!= ParentProperty
.Kind
)
1594 // If the kind is the same but the raw string not, we don't want
1595 // to skip out on the property.
1596 MergedProperty
|= Property
.RawString
== ParentProperty
.RawString
;
1598 if (Property
.RawString
== ParentProperty
.RawString
&&
1599 Selector
.ScoreOrCondition
== ParentSelector
.ScoreOrCondition
)
1602 if (Selector
.Kind
== llvm::omp::TraitSelector::user_condition
) {
1603 Diag(Loc
, diag::err_omp_declare_variant_nested_user_condition
);
1604 } else if (Selector
.ScoreOrCondition
!=
1605 ParentSelector
.ScoreOrCondition
) {
1606 Diag(Loc
, diag::err_omp_declare_variant_duplicate_nested_trait
)
1607 << getOpenMPContextTraitPropertyName(
1608 ParentProperty
.Kind
, ParentProperty
.RawString
)
1609 << getOpenMPContextTraitSelectorName(ParentSelector
.Kind
)
1610 << getOpenMPContextTraitSetName(ParentSet
.Kind
);
1613 if (!MergedProperty
)
1614 Selector
.Properties
.push_back(ParentProperty
);
1617 if (!MergedSelector
)
1618 Set
.Selectors
.push_back(ParentSelector
);
1622 TI
.Sets
.push_back(ParentSet
);
1628 /// <clause> [clause[ [,] clause] ... ]
1630 /// clauses: for error directive
1631 /// 'at' '(' compilation | execution ')'
1632 /// 'severity' '(' fatal | warning ')'
1633 /// 'message' '(' msg-string ')'
1635 void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind
,
1636 SmallVectorImpl
<OMPClause
*> &Clauses
,
1637 SourceLocation Loc
) {
1638 SmallVector
<llvm::PointerIntPair
<OMPClause
*, 1, bool>,
1639 llvm::omp::Clause_enumSize
+ 1>
1640 FirstClauses(llvm::omp::Clause_enumSize
+ 1);
1641 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
1642 OpenMPClauseKind CKind
= Tok
.isAnnotation()
1644 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
1645 Actions
.StartOpenMPClause(CKind
);
1646 OMPClause
*Clause
= ParseOpenMPClause(
1647 DKind
, CKind
, !FirstClauses
[unsigned(CKind
)].getInt());
1648 SkipUntil(tok::comma
, tok::identifier
, tok::annot_pragma_openmp_end
,
1650 FirstClauses
[unsigned(CKind
)].setInt(true);
1651 if (Clause
!= nullptr)
1652 Clauses
.push_back(Clause
);
1653 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
1654 Actions
.EndOpenMPClause();
1658 if (Tok
.is(tok::comma
))
1660 Actions
.EndOpenMPClause();
1664 /// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
1668 /// 'ext_IMPL_DEFINED'
1669 /// 'absent' '(' directive-name [, directive-name]* ')'
1670 /// 'contains' '(' directive-name [, directive-name]* ')'
1671 /// 'holds' '(' scalar-expression ')'
1673 /// 'no_openmp_routines'
1674 /// 'no_parallelism'
1676 void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind
,
1677 SourceLocation Loc
) {
1678 SmallVector
<std::string
, 4> Assumptions
;
1679 bool SkippedClauses
= false;
1681 auto SkipBraces
= [&](llvm::StringRef Spelling
, bool IssueNote
) {
1682 BalancedDelimiterTracker
T(*this, tok::l_paren
,
1683 tok::annot_pragma_openmp_end
);
1684 if (T
.expectAndConsume(diag::err_expected_lparen_after
, Spelling
.data()))
1687 if (IssueNote
&& T
.getCloseLocation().isValid())
1688 Diag(T
.getCloseLocation(),
1689 diag::note_omp_assumption_clause_continue_here
);
1692 /// Helper to determine which AssumptionClauseMapping (ACM) in the
1693 /// AssumptionClauseMappings table matches \p RawString. The return value is
1694 /// the index of the matching ACM into the table or -1 if there was no match.
1695 auto MatchACMClause
= [&](StringRef RawString
) {
1696 llvm::StringSwitch
<int> SS(RawString
);
1697 unsigned ACMIdx
= 0;
1698 for (const AssumptionClauseMappingInfo
&ACMI
: AssumptionClauseMappings
) {
1699 if (ACMI
.StartsWith
)
1700 SS
.StartsWith(ACMI
.Identifier
, ACMIdx
++);
1702 SS
.Case(ACMI
.Identifier
, ACMIdx
++);
1704 return SS
.Default(-1);
1707 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
1708 IdentifierInfo
*II
= nullptr;
1709 SourceLocation StartLoc
= Tok
.getLocation();
1711 if (Tok
.isAnyIdentifier()) {
1712 II
= Tok
.getIdentifierInfo();
1713 Idx
= MatchACMClause(II
->getName());
1717 bool NextIsLPar
= Tok
.is(tok::l_paren
);
1718 // Handle unknown clauses by skipping them.
1720 Diag(StartLoc
, diag::warn_omp_unknown_assumption_clause_missing_id
)
1721 << llvm::omp::getOpenMPDirectiveName(DKind
)
1722 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar
;
1724 SkipBraces(II
? II
->getName() : "", /* IssueNote */ true);
1725 SkippedClauses
= true;
1728 const AssumptionClauseMappingInfo
&ACMI
= AssumptionClauseMappings
[Idx
];
1729 if (ACMI
.HasDirectiveList
|| ACMI
.HasExpression
) {
1730 // TODO: We ignore absent, contains, and holds assumptions for now. We
1731 // also do not verify the content in the parenthesis at all.
1732 SkippedClauses
= true;
1733 SkipBraces(II
->getName(), /* IssueNote */ false);
1738 Diag(Tok
.getLocation(),
1739 diag::warn_omp_unknown_assumption_clause_without_args
)
1741 SkipBraces(II
->getName(), /* IssueNote */ true);
1744 assert(II
&& "Expected an identifier clause!");
1745 std::string Assumption
= II
->getName().str();
1746 if (ACMI
.StartsWith
)
1747 Assumption
= "ompx_" + Assumption
.substr(ACMI
.Identifier
.size());
1749 Assumption
= "omp_" + Assumption
;
1750 Assumptions
.push_back(Assumption
);
1753 Actions
.ActOnOpenMPAssumesDirective(Loc
, DKind
, Assumptions
, SkippedClauses
);
1756 void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc
) {
1757 if (Actions
.isInOpenMPAssumeScope())
1758 Actions
.ActOnOpenMPEndAssumesDirective();
1760 Diag(Loc
, diag::err_expected_begin_assumes
);
1763 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1766 /// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')
1768 /// proc_bind-clause:
1769 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1771 /// device_type-clause:
1772 /// 'device_type' '(' 'host' | 'nohost' | 'any' )'
1774 struct SimpleClauseData
{
1777 SourceLocation LOpen
;
1778 SourceLocation TypeLoc
;
1779 SourceLocation RLoc
;
1780 SimpleClauseData(unsigned Type
, SourceLocation Loc
, SourceLocation LOpen
,
1781 SourceLocation TypeLoc
, SourceLocation RLoc
)
1782 : Type(Type
), Loc(Loc
), LOpen(LOpen
), TypeLoc(TypeLoc
), RLoc(RLoc
) {}
1784 } // anonymous namespace
1786 static std::optional
<SimpleClauseData
>
1787 parseOpenMPSimpleClause(Parser
&P
, OpenMPClauseKind Kind
) {
1788 const Token
&Tok
= P
.getCurToken();
1789 SourceLocation Loc
= Tok
.getLocation();
1790 SourceLocation LOpen
= P
.ConsumeToken();
1792 BalancedDelimiterTracker
T(P
, tok::l_paren
, tok::annot_pragma_openmp_end
);
1793 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
1794 getOpenMPClauseName(Kind
).data()))
1795 return std::nullopt
;
1797 unsigned Type
= getOpenMPSimpleClauseType(
1798 Kind
, Tok
.isAnnotation() ? "" : P
.getPreprocessor().getSpelling(Tok
),
1800 SourceLocation TypeLoc
= Tok
.getLocation();
1801 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
1802 Tok
.isNot(tok::annot_pragma_openmp_end
))
1803 P
.ConsumeAnyToken();
1806 SourceLocation RLoc
= Tok
.getLocation();
1807 if (!T
.consumeClose())
1808 RLoc
= T
.getCloseLocation();
1810 return SimpleClauseData(Type
, Loc
, LOpen
, TypeLoc
, RLoc
);
1813 void Parser::ParseOMPDeclareTargetClauses(
1814 Sema::DeclareTargetContextInfo
&DTCI
) {
1815 SourceLocation DeviceTypeLoc
;
1816 bool RequiresToOrLinkOrIndirectClause
= false;
1817 bool HasToOrLinkOrIndirectClause
= false;
1818 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
1819 OMPDeclareTargetDeclAttr::MapTypeTy MT
= OMPDeclareTargetDeclAttr::MT_To
;
1820 bool HasIdentifier
= Tok
.is(tok::identifier
);
1821 if (HasIdentifier
) {
1822 // If we see any clause we need a to or link clause.
1823 RequiresToOrLinkOrIndirectClause
= true;
1824 IdentifierInfo
*II
= Tok
.getIdentifierInfo();
1825 StringRef ClauseName
= II
->getName();
1826 bool IsDeviceTypeClause
=
1827 getLangOpts().OpenMP
>= 50 &&
1828 getOpenMPClauseKind(ClauseName
) == OMPC_device_type
;
1830 bool IsIndirectClause
= getLangOpts().OpenMP
>= 51 &&
1831 getOpenMPClauseKind(ClauseName
) == OMPC_indirect
;
1832 if (DTCI
.Indirect
&& IsIndirectClause
) {
1833 Diag(Tok
, diag::err_omp_more_one_clause
)
1834 << getOpenMPDirectiveName(OMPD_declare_target
)
1835 << getOpenMPClauseName(OMPC_indirect
) << 0;
1838 bool IsToEnterOrLinkClause
=
1839 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName
, MT
);
1840 assert((!IsDeviceTypeClause
|| !IsToEnterOrLinkClause
) &&
1843 // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1845 if (getLangOpts().OpenMP
>= 52 && ClauseName
== "to") {
1846 Diag(Tok
, diag::err_omp_declare_target_unexpected_to_clause
);
1849 if (getLangOpts().OpenMP
<= 51 && ClauseName
== "enter") {
1850 Diag(Tok
, diag::err_omp_declare_target_unexpected_enter_clause
);
1854 if (!IsDeviceTypeClause
&& !IsIndirectClause
&&
1855 DTCI
.Kind
== OMPD_begin_declare_target
) {
1856 Diag(Tok
, diag::err_omp_declare_target_unexpected_clause
)
1857 << ClauseName
<< (getLangOpts().OpenMP
>= 51 ? 3 : 0);
1860 if (!IsDeviceTypeClause
&& !IsToEnterOrLinkClause
&& !IsIndirectClause
) {
1861 Diag(Tok
, getLangOpts().OpenMP
>= 52
1862 ? diag::err_omp_declare_target_unexpected_clause_52
1863 : diag::err_omp_declare_target_unexpected_clause
)
1865 << (getLangOpts().OpenMP
>= 51
1867 : getLangOpts().OpenMP
>= 50 ? 2 : 1);
1871 if (IsToEnterOrLinkClause
|| IsIndirectClause
)
1872 HasToOrLinkOrIndirectClause
= true;
1874 if (IsIndirectClause
) {
1875 if (!ParseOpenMPIndirectClause(DTCI
, /*ParseOnly*/ false))
1879 // Parse 'device_type' clause and go to next clause if any.
1880 if (IsDeviceTypeClause
) {
1881 std::optional
<SimpleClauseData
> DevTypeData
=
1882 parseOpenMPSimpleClause(*this, OMPC_device_type
);
1884 if (DeviceTypeLoc
.isValid()) {
1885 // We already saw another device_type clause, diagnose it.
1886 Diag(DevTypeData
->Loc
,
1887 diag::warn_omp_more_one_device_type_clause
);
1890 switch (static_cast<OpenMPDeviceType
>(DevTypeData
->Type
)) {
1891 case OMPC_DEVICE_TYPE_any
:
1892 DTCI
.DT
= OMPDeclareTargetDeclAttr::DT_Any
;
1894 case OMPC_DEVICE_TYPE_host
:
1895 DTCI
.DT
= OMPDeclareTargetDeclAttr::DT_Host
;
1897 case OMPC_DEVICE_TYPE_nohost
:
1898 DTCI
.DT
= OMPDeclareTargetDeclAttr::DT_NoHost
;
1900 case OMPC_DEVICE_TYPE_unknown
:
1901 llvm_unreachable("Unexpected device_type");
1903 DeviceTypeLoc
= DevTypeData
->Loc
;
1910 if (DTCI
.Kind
== OMPD_declare_target
|| HasIdentifier
) {
1911 auto &&Callback
= [this, MT
, &DTCI
](CXXScopeSpec
&SS
,
1912 DeclarationNameInfo NameInfo
) {
1914 Actions
.lookupOpenMPDeclareTargetName(getCurScope(), SS
, NameInfo
);
1917 Sema::DeclareTargetContextInfo::MapInfo MI
{MT
, NameInfo
.getLoc()};
1918 bool FirstMapping
= DTCI
.ExplicitlyMapped
.try_emplace(ND
, MI
).second
;
1920 Diag(NameInfo
.getLoc(), diag::err_omp_declare_target_multiple
)
1921 << NameInfo
.getName();
1923 if (ParseOpenMPSimpleVarList(OMPD_declare_target
, Callback
,
1924 /*AllowScopeSpecifier=*/true))
1928 if (Tok
.is(tok::l_paren
)) {
1930 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause
);
1933 if (!HasIdentifier
&& Tok
.isNot(tok::annot_pragma_openmp_end
)) {
1935 getLangOpts().OpenMP
>= 52
1936 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1937 : diag::err_omp_declare_target_wrong_clause_after_implicit_to
);
1941 // Consume optional ','.
1942 if (Tok
.is(tok::comma
))
1946 if (DTCI
.Indirect
&& DTCI
.DT
!= OMPDeclareTargetDeclAttr::DT_Any
)
1947 Diag(DeviceTypeLoc
, diag::err_omp_declare_target_indirect_device_type
);
1949 // For declare target require at least 'to' or 'link' to be present.
1950 if (DTCI
.Kind
== OMPD_declare_target
&& RequiresToOrLinkOrIndirectClause
&&
1951 !HasToOrLinkOrIndirectClause
)
1953 getLangOpts().OpenMP
>= 52
1954 ? diag::err_omp_declare_target_missing_enter_or_link_clause
1955 : diag::err_omp_declare_target_missing_to_or_link_clause
)
1956 << (getLangOpts().OpenMP
>= 51 ? 1 : 0);
1958 SkipUntil(tok::annot_pragma_openmp_end
, StopBeforeMatch
);
1961 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind
) {
1962 // The last seen token is annot_pragma_openmp_end - need to check for
1964 if (Tok
.is(tok::annot_pragma_openmp_end
))
1967 Diag(Tok
, diag::warn_omp_extra_tokens_at_eol
)
1968 << getOpenMPDirectiveName(DKind
);
1969 while (Tok
.isNot(tok::annot_pragma_openmp_end
))
1973 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind
,
1974 OpenMPDirectiveKind ExpectedKind
,
1975 OpenMPDirectiveKind FoundKind
,
1976 SourceLocation BeginLoc
,
1977 SourceLocation FoundLoc
,
1978 bool SkipUntilOpenMPEnd
) {
1979 int DiagSelection
= ExpectedKind
== OMPD_end_declare_target
? 0 : 1;
1981 if (FoundKind
== ExpectedKind
) {
1983 skipUntilPragmaOpenMPEnd(ExpectedKind
);
1987 Diag(FoundLoc
, diag::err_expected_end_declare_target_or_variant
)
1989 Diag(BeginLoc
, diag::note_matching
)
1990 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind
) + "'").str();
1991 if (SkipUntilOpenMPEnd
)
1992 SkipUntil(tok::annot_pragma_openmp_end
, StopBeforeMatch
);
1995 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind
,
1996 OpenMPDirectiveKind EndDKind
,
1997 SourceLocation DKLoc
) {
1998 parseOMPEndDirective(BeginDKind
, OMPD_end_declare_target
, EndDKind
, DKLoc
,
2000 /* SkipUntilOpenMPEnd */ false);
2001 // Skip the last annot_pragma_openmp_end.
2002 if (Tok
.is(tok::annot_pragma_openmp_end
))
2003 ConsumeAnnotationToken();
2006 /// Parsing of declarative OpenMP directives.
2008 /// threadprivate-directive:
2009 /// annot_pragma_openmp 'threadprivate' simple-variable-list
2010 /// annot_pragma_openmp_end
2012 /// allocate-directive:
2013 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
2014 /// annot_pragma_openmp_end
2016 /// declare-reduction-directive:
2017 /// annot_pragma_openmp 'declare' 'reduction' [...]
2018 /// annot_pragma_openmp_end
2020 /// declare-mapper-directive:
2021 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2022 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
2023 /// annot_pragma_openmp_end
2025 /// declare-simd-directive:
2026 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
2027 /// annot_pragma_openmp_end
2028 /// <function declaration/definition>
2030 /// requires directive:
2031 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
2032 /// annot_pragma_openmp_end
2034 /// assumes directive:
2035 /// annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ]
2036 /// annot_pragma_openmp_end
2038 /// annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ]
2039 /// annot_pragma_openmp 'end assumes'
2040 /// annot_pragma_openmp_end
2042 Parser::DeclGroupPtrTy
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
2043 AccessSpecifier
&AS
, ParsedAttributes
&Attrs
, bool Delayed
,
2044 DeclSpec::TST TagType
, Decl
*Tag
) {
2045 assert(Tok
.isOneOf(tok::annot_pragma_openmp
, tok::annot_attr_openmp
) &&
2046 "Not an OpenMP directive!");
2047 ParsingOpenMPDirectiveRAII
DirScope(*this);
2048 ParenBraceBracketBalancer
BalancerRAIIObj(*this);
2051 OpenMPDirectiveKind DKind
;
2053 TentativeParsingAction
TPA(*this);
2054 Loc
= ConsumeAnnotationToken();
2055 DKind
= parseOpenMPDirectiveKind(*this);
2056 if (DKind
== OMPD_declare_reduction
|| DKind
== OMPD_declare_mapper
) {
2057 // Need to delay parsing until completion of the parent class.
2061 Toks
.push_back(Tok
);
2062 while (Cnt
&& Tok
.isNot(tok::eof
)) {
2063 (void)ConsumeAnyToken();
2064 if (Tok
.isOneOf(tok::annot_pragma_openmp
, tok::annot_attr_openmp
))
2066 else if (Tok
.is(tok::annot_pragma_openmp_end
))
2068 Toks
.push_back(Tok
);
2070 // Skip last annot_pragma_openmp_end.
2072 (void)ConsumeAnyToken();
2073 auto *LP
= new LateParsedPragma(this, AS
);
2075 getCurrentClass().LateParsedDeclarations
.push_back(LP
);
2080 Loc
= ConsumeAnnotationToken();
2081 DKind
= parseOpenMPDirectiveKind(*this);
2085 case OMPD_threadprivate
: {
2087 DeclDirectiveListParserHelper
Helper(this, DKind
);
2088 if (!ParseOpenMPSimpleVarList(DKind
, Helper
,
2089 /*AllowScopeSpecifier=*/true)) {
2090 skipUntilPragmaOpenMPEnd(DKind
);
2091 // Skip the last annot_pragma_openmp_end.
2092 ConsumeAnnotationToken();
2093 return Actions
.ActOnOpenMPThreadprivateDirective(Loc
,
2094 Helper
.getIdentifiers());
2098 case OMPD_allocate
: {
2100 DeclDirectiveListParserHelper
Helper(this, DKind
);
2101 if (!ParseOpenMPSimpleVarList(DKind
, Helper
,
2102 /*AllowScopeSpecifier=*/true)) {
2103 SmallVector
<OMPClause
*, 1> Clauses
;
2104 if (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2105 SmallVector
<llvm::PointerIntPair
<OMPClause
*, 1, bool>,
2106 llvm::omp::Clause_enumSize
+ 1>
2107 FirstClauses(llvm::omp::Clause_enumSize
+ 1);
2108 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2109 OpenMPClauseKind CKind
=
2110 Tok
.isAnnotation() ? OMPC_unknown
2111 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
2112 Actions
.StartOpenMPClause(CKind
);
2113 OMPClause
*Clause
= ParseOpenMPClause(
2114 OMPD_allocate
, CKind
, !FirstClauses
[unsigned(CKind
)].getInt());
2115 SkipUntil(tok::comma
, tok::identifier
, tok::annot_pragma_openmp_end
,
2117 FirstClauses
[unsigned(CKind
)].setInt(true);
2118 if (Clause
!= nullptr)
2119 Clauses
.push_back(Clause
);
2120 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
2121 Actions
.EndOpenMPClause();
2125 if (Tok
.is(tok::comma
))
2127 Actions
.EndOpenMPClause();
2129 skipUntilPragmaOpenMPEnd(DKind
);
2131 // Skip the last annot_pragma_openmp_end.
2132 ConsumeAnnotationToken();
2133 return Actions
.ActOnOpenMPAllocateDirective(Loc
, Helper
.getIdentifiers(),
2138 case OMPD_requires
: {
2139 SourceLocation StartLoc
= ConsumeToken();
2140 SmallVector
<OMPClause
*, 5> Clauses
;
2141 SmallVector
<llvm::PointerIntPair
<OMPClause
*, 1, bool>,
2142 llvm::omp::Clause_enumSize
+ 1>
2143 FirstClauses(llvm::omp::Clause_enumSize
+ 1);
2144 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
2145 Diag(Tok
, diag::err_omp_expected_clause
)
2146 << getOpenMPDirectiveName(OMPD_requires
);
2149 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2150 OpenMPClauseKind CKind
= Tok
.isAnnotation()
2152 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
2153 Actions
.StartOpenMPClause(CKind
);
2154 OMPClause
*Clause
= ParseOpenMPClause(
2155 OMPD_requires
, CKind
, !FirstClauses
[unsigned(CKind
)].getInt());
2156 SkipUntil(tok::comma
, tok::identifier
, tok::annot_pragma_openmp_end
,
2158 FirstClauses
[unsigned(CKind
)].setInt(true);
2159 if (Clause
!= nullptr)
2160 Clauses
.push_back(Clause
);
2161 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
2162 Actions
.EndOpenMPClause();
2166 if (Tok
.is(tok::comma
))
2168 Actions
.EndOpenMPClause();
2170 // Consume final annot_pragma_openmp_end
2171 if (Clauses
.empty()) {
2172 Diag(Tok
, diag::err_omp_expected_clause
)
2173 << getOpenMPDirectiveName(OMPD_requires
);
2174 ConsumeAnnotationToken();
2177 ConsumeAnnotationToken();
2178 return Actions
.ActOnOpenMPRequiresDirective(StartLoc
, Clauses
);
2181 SmallVector
<OMPClause
*, 1> Clauses
;
2182 SourceLocation StartLoc
= ConsumeToken();
2183 ParseOpenMPClauses(DKind
, Clauses
, StartLoc
);
2184 Actions
.ActOnOpenMPErrorDirective(Clauses
, StartLoc
, SourceLocation(),
2185 /*InExContext = */ false);
2189 case OMPD_begin_assumes
:
2190 ParseOpenMPAssumesDirective(DKind
, ConsumeToken());
2192 case OMPD_end_assumes
:
2193 ParseOpenMPEndAssumesDirective(ConsumeToken());
2195 case OMPD_declare_reduction
:
2197 if (DeclGroupPtrTy Res
= ParseOpenMPDeclareReductionDirective(AS
)) {
2198 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction
);
2199 // Skip the last annot_pragma_openmp_end.
2200 ConsumeAnnotationToken();
2204 case OMPD_declare_mapper
: {
2206 if (DeclGroupPtrTy Res
= ParseOpenMPDeclareMapperDirective(AS
)) {
2207 // Skip the last annot_pragma_openmp_end.
2208 ConsumeAnnotationToken();
2213 case OMPD_begin_declare_variant
: {
2215 // { #pragma omp begin declare variant clause }
2216 // <function-declaration-or-definition-sequence>
2217 // { #pragma omp end declare variant }
2220 OMPTraitInfo
*ParentTI
= Actions
.getOMPTraitInfoForSurroundingScope();
2221 ASTContext
&ASTCtx
= Actions
.getASTContext();
2222 OMPTraitInfo
&TI
= ASTCtx
.getNewOMPTraitInfo();
2223 if (parseOMPDeclareVariantMatchClause(Loc
, TI
, ParentTI
)) {
2224 while (!SkipUntil(tok::annot_pragma_openmp_end
, Parser::StopBeforeMatch
))
2226 // Skip the last annot_pragma_openmp_end.
2227 (void)ConsumeAnnotationToken();
2231 // Skip last tokens.
2232 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant
);
2234 ParsingOpenMPDirectiveRAII
NormalScope(*this, /*Value=*/false);
2236 VariantMatchInfo VMI
;
2237 TI
.getAsVariantMatchInfo(ASTCtx
, VMI
);
2239 std::function
<void(StringRef
)> DiagUnknownTrait
=
2240 [this, Loc
](StringRef ISATrait
) {
2241 // TODO Track the selector locations in a way that is accessible here
2242 // to improve the diagnostic location.
2243 Diag(Loc
, diag::warn_unknown_declare_variant_isa_trait
) << ISATrait
;
2245 TargetOMPContext
OMPCtx(
2246 ASTCtx
, std::move(DiagUnknownTrait
),
2247 /* CurrentFunctionDecl */ nullptr,
2248 /* ConstructTraits */ ArrayRef
<llvm::omp::TraitProperty
>());
2250 if (isVariantApplicableInContext(VMI
, OMPCtx
, /* DeviceSetOnly */ true)) {
2251 Actions
.ActOnOpenMPBeginDeclareVariant(Loc
, TI
);
2255 // Elide all the code till the matching end declare variant was found.
2256 unsigned Nesting
= 1;
2257 SourceLocation DKLoc
;
2258 OpenMPDirectiveKind DK
= OMPD_unknown
;
2260 DKLoc
= Tok
.getLocation();
2261 DK
= parseOpenMPDirectiveKind(*this);
2262 if (DK
== OMPD_end_declare_variant
)
2264 else if (DK
== OMPD_begin_declare_variant
)
2266 if (!Nesting
|| isEofOrEom())
2271 parseOMPEndDirective(OMPD_begin_declare_variant
, OMPD_end_declare_variant
,
2272 DK
, Loc
, DKLoc
, /* SkipUntilOpenMPEnd */ true);
2277 case OMPD_end_declare_variant
: {
2278 if (Actions
.isInOpenMPDeclareVariantScope())
2279 Actions
.ActOnOpenMPEndDeclareVariant();
2281 Diag(Loc
, diag::err_expected_begin_declare_variant
);
2285 case OMPD_declare_variant
:
2286 case OMPD_declare_simd
: {
2288 // { #pragma omp declare {simd|variant} }
2289 // <function-declaration-or-definition>
2292 Toks
.push_back(Tok
);
2294 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2295 Toks
.push_back(Tok
);
2298 Toks
.push_back(Tok
);
2302 if (Tok
.isOneOf(tok::annot_pragma_openmp
, tok::annot_attr_openmp
)) {
2303 Ptr
= ParseOpenMPDeclarativeDirectiveWithExtDecl(AS
, Attrs
, Delayed
,
2305 } else if (Tok
.isNot(tok::r_brace
) && !isEofOrEom()) {
2306 // Here we expect to see some function declaration.
2307 if (AS
== AS_none
) {
2308 assert(TagType
== DeclSpec::TST_unspecified
);
2309 ParsedAttributes
EmptyDeclSpecAttrs(AttrFactory
);
2310 MaybeParseCXX11Attributes(Attrs
);
2311 ParsingDeclSpec
PDS(*this);
2312 Ptr
= ParseExternalDeclaration(Attrs
, EmptyDeclSpecAttrs
, &PDS
);
2315 ParseCXXClassMemberDeclarationWithPragmas(AS
, Attrs
, TagType
, Tag
);
2319 Diag(Loc
, diag::err_omp_decl_in_declare_simd_variant
)
2320 << (DKind
== OMPD_declare_simd
? 0 : 1);
2321 return DeclGroupPtrTy();
2323 if (DKind
== OMPD_declare_simd
)
2324 return ParseOMPDeclareSimdClauses(Ptr
, Toks
, Loc
);
2325 assert(DKind
== OMPD_declare_variant
&&
2326 "Expected declare variant directive only");
2327 ParseOMPDeclareVariantClauses(Ptr
, Toks
, Loc
);
2330 case OMPD_begin_declare_target
:
2331 case OMPD_declare_target
: {
2332 SourceLocation DTLoc
= ConsumeAnyToken();
2333 bool HasClauses
= Tok
.isNot(tok::annot_pragma_openmp_end
);
2334 Sema::DeclareTargetContextInfo
DTCI(DKind
, DTLoc
);
2336 ParseOMPDeclareTargetClauses(DTCI
);
2337 bool HasImplicitMappings
= DKind
== OMPD_begin_declare_target
||
2339 (DTCI
.ExplicitlyMapped
.empty() && DTCI
.Indirect
);
2341 // Skip the last annot_pragma_openmp_end.
2344 if (HasImplicitMappings
) {
2345 Actions
.ActOnStartOpenMPDeclareTargetContext(DTCI
);
2349 Actions
.ActOnFinishedOpenMPDeclareTargetContext(DTCI
);
2350 llvm::SmallVector
<Decl
*, 4> Decls
;
2351 for (auto &It
: DTCI
.ExplicitlyMapped
)
2352 Decls
.push_back(It
.first
);
2353 return Actions
.BuildDeclaratorGroup(Decls
);
2355 case OMPD_end_declare_target
: {
2356 if (!Actions
.isInOpenMPDeclareTargetContext()) {
2357 Diag(Tok
, diag::err_omp_unexpected_directive
)
2358 << 1 << getOpenMPDirectiveName(DKind
);
2361 const Sema::DeclareTargetContextInfo
&DTCI
=
2362 Actions
.ActOnOpenMPEndDeclareTargetDirective();
2363 ParseOMPEndDeclareTargetDirective(DTCI
.Kind
, DKind
, DTCI
.Loc
);
2367 Diag(Tok
, diag::err_omp_unknown_directive
);
2374 case OMPD_taskyield
:
2377 case OMPD_taskgroup
:
2389 case OMPD_parallel_for
:
2390 case OMPD_parallel_for_simd
:
2391 case OMPD_parallel_sections
:
2392 case OMPD_parallel_master
:
2393 case OMPD_parallel_masked
:
2397 case OMPD_cancellation_point
:
2399 case OMPD_target_data
:
2400 case OMPD_target_enter_data
:
2401 case OMPD_target_exit_data
:
2402 case OMPD_target_parallel
:
2403 case OMPD_target_parallel_for
:
2405 case OMPD_taskloop_simd
:
2406 case OMPD_master_taskloop
:
2407 case OMPD_master_taskloop_simd
:
2408 case OMPD_parallel_master_taskloop
:
2409 case OMPD_parallel_master_taskloop_simd
:
2410 case OMPD_masked_taskloop
:
2411 case OMPD_masked_taskloop_simd
:
2412 case OMPD_parallel_masked_taskloop
:
2413 case OMPD_parallel_masked_taskloop_simd
:
2414 case OMPD_distribute
:
2415 case OMPD_target_update
:
2416 case OMPD_distribute_parallel_for
:
2417 case OMPD_distribute_parallel_for_simd
:
2418 case OMPD_distribute_simd
:
2419 case OMPD_target_parallel_for_simd
:
2420 case OMPD_target_simd
:
2422 case OMPD_teams_distribute
:
2423 case OMPD_teams_distribute_simd
:
2424 case OMPD_teams_distribute_parallel_for_simd
:
2425 case OMPD_teams_distribute_parallel_for
:
2426 case OMPD_target_teams
:
2427 case OMPD_target_teams_distribute
:
2428 case OMPD_target_teams_distribute_parallel_for
:
2429 case OMPD_target_teams_distribute_parallel_for_simd
:
2430 case OMPD_target_teams_distribute_simd
:
2433 case OMPD_metadirective
:
2435 case OMPD_teams_loop
:
2436 case OMPD_target_teams_loop
:
2437 case OMPD_parallel_loop
:
2438 case OMPD_target_parallel_loop
:
2439 Diag(Tok
, diag::err_omp_unexpected_directive
)
2440 << 1 << getOpenMPDirectiveName(DKind
);
2445 while (Tok
.isNot(tok::annot_pragma_openmp_end
))
2451 /// Parsing of declarative or executable OpenMP directives.
2453 /// threadprivate-directive:
2454 /// annot_pragma_openmp 'threadprivate' simple-variable-list
2455 /// annot_pragma_openmp_end
2457 /// allocate-directive:
2458 /// annot_pragma_openmp 'allocate' simple-variable-list
2459 /// annot_pragma_openmp_end
2461 /// declare-reduction-directive:
2462 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
2463 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
2464 /// ('omp_priv' '=' <expression>|<function_call>) ')']
2465 /// annot_pragma_openmp_end
2467 /// declare-mapper-directive:
2468 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2469 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
2470 /// annot_pragma_openmp_end
2472 /// executable-directive:
2473 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
2474 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2475 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2476 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
2477 /// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2478 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2479 /// 'master taskloop' | 'master taskloop simd' | 'parallel master
2480 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2481 /// enter data' | 'target exit data' | 'target parallel' | 'target
2482 /// parallel for' | 'target update' | 'distribute parallel for' |
2483 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel
2484 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2485 /// simd' | 'teams distribute parallel for simd' | 'teams distribute
2486 /// parallel for' | 'target teams' | 'target teams distribute' | 'target
2487 /// teams distribute parallel for' | 'target teams distribute parallel
2488 /// for simd' | 'target teams distribute simd' | 'masked' |
2489 /// 'parallel masked' {clause} annot_pragma_openmp_end
2491 StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2492 ParsedStmtContext StmtCtx
, bool ReadDirectiveWithinMetadirective
) {
2493 if (!ReadDirectiveWithinMetadirective
)
2494 assert(Tok
.isOneOf(tok::annot_pragma_openmp
, tok::annot_attr_openmp
) &&
2495 "Not an OpenMP directive!");
2496 ParsingOpenMPDirectiveRAII
DirScope(*this);
2497 ParenBraceBracketBalancer
BalancerRAIIObj(*this);
2498 SmallVector
<OMPClause
*, 5> Clauses
;
2499 SmallVector
<llvm::PointerIntPair
<OMPClause
*, 1, bool>,
2500 llvm::omp::Clause_enumSize
+ 1>
2501 FirstClauses(llvm::omp::Clause_enumSize
+ 1);
2502 unsigned ScopeFlags
= Scope::FnScope
| Scope::DeclScope
|
2503 Scope::CompoundStmtScope
| Scope::OpenMPDirectiveScope
;
2504 SourceLocation Loc
= ReadDirectiveWithinMetadirective
2506 : ConsumeAnnotationToken(),
2508 OpenMPDirectiveKind DKind
= parseOpenMPDirectiveKind(*this);
2509 if (ReadDirectiveWithinMetadirective
&& DKind
== OMPD_unknown
) {
2510 Diag(Tok
, diag::err_omp_unknown_directive
);
2513 OpenMPDirectiveKind CancelRegion
= OMPD_unknown
;
2514 // Name of critical directive.
2515 DeclarationNameInfo DirName
;
2516 StmtResult Directive
= StmtError();
2517 bool HasAssociatedStatement
= true;
2522 // If we are parsing the directive within a metadirective, the directive
2524 if (ReadDirectiveWithinMetadirective
&& Tok
.is(tok::r_paren
))
2525 while (Tok
.isNot(tok::annot_pragma_openmp_end
))
2528 skipUntilPragmaOpenMPEnd(DKind
);
2529 if (Tok
.is(tok::annot_pragma_openmp_end
))
2530 ConsumeAnnotationToken();
2531 // return an empty statement
2533 case OMPD_metadirective
: {
2535 SmallVector
<VariantMatchInfo
, 4> VMIs
;
2537 // First iteration of parsing all clauses of metadirective.
2538 // This iteration only parses and collects all context selector ignoring the
2539 // associated directives.
2540 TentativeParsingAction
TPA(*this);
2541 ASTContext
&ASTContext
= Actions
.getASTContext();
2543 BalancedDelimiterTracker
T(*this, tok::l_paren
,
2544 tok::annot_pragma_openmp_end
);
2545 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2546 OpenMPClauseKind CKind
= Tok
.isAnnotation()
2548 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
2549 SourceLocation Loc
= ConsumeToken();
2552 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
2553 getOpenMPClauseName(CKind
).data()))
2556 OMPTraitInfo
&TI
= Actions
.getASTContext().getNewOMPTraitInfo();
2557 if (CKind
== OMPC_when
) {
2558 // parse and get OMPTraitInfo to pass to the When clause
2559 parseOMPContextSelectors(Loc
, TI
);
2560 if (TI
.Sets
.size() == 0) {
2561 Diag(Tok
, diag::err_omp_expected_context_selector
) << "when clause";
2567 if (Tok
.is(tok::colon
))
2570 Diag(Tok
, diag::err_omp_expected_colon
) << "when clause";
2575 // Skip Directive for now. We will parse directive in the second iteration
2577 while (Tok
.isNot(tok::r_paren
) || paren
!= 0) {
2578 if (Tok
.is(tok::l_paren
))
2580 if (Tok
.is(tok::r_paren
))
2582 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
2583 Diag(Tok
, diag::err_omp_expected_punc
)
2584 << getOpenMPClauseName(CKind
) << 0;
2591 if (Tok
.is(tok::r_paren
))
2594 VariantMatchInfo VMI
;
2595 TI
.getAsVariantMatchInfo(ASTContext
, VMI
);
2597 VMIs
.push_back(VMI
);
2601 // End of the first iteration. Parser is reset to the start of metadirective
2603 std::function
<void(StringRef
)> DiagUnknownTrait
=
2604 [this, Loc
](StringRef ISATrait
) {
2605 // TODO Track the selector locations in a way that is accessible here
2606 // to improve the diagnostic location.
2607 Diag(Loc
, diag::warn_unknown_declare_variant_isa_trait
) << ISATrait
;
2609 TargetOMPContext
OMPCtx(ASTContext
, std::move(DiagUnknownTrait
),
2610 /* CurrentFunctionDecl */ nullptr,
2611 ArrayRef
<llvm::omp::TraitProperty
>());
2613 // A single match is returned for OpenMP 5.0
2614 int BestIdx
= getBestVariantMatchForContext(VMIs
, OMPCtx
);
2617 // In OpenMP 5.0 metadirective is either replaced by another directive or
2619 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2620 // found by getBestWhenMatchForContext.
2621 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2622 // OpenMP 5.0 implementation - Skip to the best index found.
2623 if (Idx
++ != BestIdx
) {
2624 ConsumeToken(); // Consume clause name
2625 T
.consumeOpen(); // Consume '('
2627 // Skip everything inside the clause
2628 while (Tok
.isNot(tok::r_paren
) || paren
!= 0) {
2629 if (Tok
.is(tok::l_paren
))
2631 if (Tok
.is(tok::r_paren
))
2636 if (Tok
.is(tok::r_paren
))
2641 OpenMPClauseKind CKind
= Tok
.isAnnotation()
2643 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
2644 SourceLocation Loc
= ConsumeToken();
2649 // Skip ContextSelectors for when clause
2650 if (CKind
== OMPC_when
) {
2651 OMPTraitInfo
&TI
= Actions
.getASTContext().getNewOMPTraitInfo();
2652 // parse and skip the ContextSelectors
2653 parseOMPContextSelectors(Loc
, TI
);
2659 // If no directive is passed, skip in OpenMP 5.0.
2660 // TODO: Generate nothing directive from OpenMP 5.1.
2661 if (Tok
.is(tok::r_paren
)) {
2662 SkipUntil(tok::annot_pragma_openmp_end
);
2667 Directive
= ParseOpenMPDeclarativeOrExecutableDirective(
2669 /*ReadDirectiveWithinMetadirective=*/true);
2674 case OMPD_threadprivate
: {
2675 // FIXME: Should this be permitted in C++?
2676 if ((StmtCtx
& ParsedStmtContext::AllowStandaloneOpenMPDirectives
) ==
2677 ParsedStmtContext()) {
2678 Diag(Tok
, diag::err_omp_immediate_directive
)
2679 << getOpenMPDirectiveName(DKind
) << 0;
2682 DeclDirectiveListParserHelper
Helper(this, DKind
);
2683 if (!ParseOpenMPSimpleVarList(DKind
, Helper
,
2684 /*AllowScopeSpecifier=*/false)) {
2685 skipUntilPragmaOpenMPEnd(DKind
);
2686 DeclGroupPtrTy Res
= Actions
.ActOnOpenMPThreadprivateDirective(
2687 Loc
, Helper
.getIdentifiers());
2688 Directive
= Actions
.ActOnDeclStmt(Res
, Loc
, Tok
.getLocation());
2690 SkipUntil(tok::annot_pragma_openmp_end
);
2693 case OMPD_allocate
: {
2694 // FIXME: Should this be permitted in C++?
2695 if ((StmtCtx
& ParsedStmtContext::AllowStandaloneOpenMPDirectives
) ==
2696 ParsedStmtContext()) {
2697 Diag(Tok
, diag::err_omp_immediate_directive
)
2698 << getOpenMPDirectiveName(DKind
) << 0;
2701 DeclDirectiveListParserHelper
Helper(this, DKind
);
2702 if (!ParseOpenMPSimpleVarList(DKind
, Helper
,
2703 /*AllowScopeSpecifier=*/false)) {
2704 SmallVector
<OMPClause
*, 1> Clauses
;
2705 if (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2706 SmallVector
<llvm::PointerIntPair
<OMPClause
*, 1, bool>,
2707 llvm::omp::Clause_enumSize
+ 1>
2708 FirstClauses(llvm::omp::Clause_enumSize
+ 1);
2709 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2710 OpenMPClauseKind CKind
=
2711 Tok
.isAnnotation() ? OMPC_unknown
2712 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
2713 Actions
.StartOpenMPClause(CKind
);
2714 OMPClause
*Clause
= ParseOpenMPClause(
2715 OMPD_allocate
, CKind
, !FirstClauses
[unsigned(CKind
)].getInt());
2716 SkipUntil(tok::comma
, tok::identifier
, tok::annot_pragma_openmp_end
,
2718 FirstClauses
[unsigned(CKind
)].setInt(true);
2719 if (Clause
!= nullptr)
2720 Clauses
.push_back(Clause
);
2721 if (Tok
.is(tok::annot_pragma_openmp_end
)) {
2722 Actions
.EndOpenMPClause();
2726 if (Tok
.is(tok::comma
))
2728 Actions
.EndOpenMPClause();
2730 skipUntilPragmaOpenMPEnd(DKind
);
2732 DeclGroupPtrTy Res
= Actions
.ActOnOpenMPAllocateDirective(
2733 Loc
, Helper
.getIdentifiers(), Clauses
);
2734 Directive
= Actions
.ActOnDeclStmt(Res
, Loc
, Tok
.getLocation());
2736 SkipUntil(tok::annot_pragma_openmp_end
);
2739 case OMPD_declare_reduction
:
2741 if (DeclGroupPtrTy Res
=
2742 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none
)) {
2743 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction
);
2745 Directive
= Actions
.ActOnDeclStmt(Res
, Loc
, Tok
.getLocation());
2747 SkipUntil(tok::annot_pragma_openmp_end
);
2750 case OMPD_declare_mapper
: {
2752 if (DeclGroupPtrTy Res
=
2753 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none
)) {
2754 // Skip the last annot_pragma_openmp_end.
2755 ConsumeAnnotationToken();
2756 Directive
= Actions
.ActOnDeclStmt(Res
, Loc
, Tok
.getLocation());
2758 SkipUntil(tok::annot_pragma_openmp_end
);
2765 case OMPD_taskyield
:
2769 case OMPD_cancellation_point
:
2771 case OMPD_target_enter_data
:
2772 case OMPD_target_exit_data
:
2773 case OMPD_target_update
:
2775 if ((StmtCtx
& ParsedStmtContext::AllowStandaloneOpenMPDirectives
) ==
2776 ParsedStmtContext()) {
2777 Diag(Tok
, diag::err_omp_immediate_directive
)
2778 << getOpenMPDirectiveName(DKind
) << 0;
2779 if (DKind
== OMPD_error
) {
2780 SkipUntil(tok::annot_pragma_openmp_end
);
2784 HasAssociatedStatement
= false;
2785 // Fall through for further analysis.
2798 case OMPD_parallel_for
:
2799 case OMPD_parallel_for_simd
:
2800 case OMPD_parallel_sections
:
2801 case OMPD_parallel_master
:
2802 case OMPD_parallel_masked
:
2808 case OMPD_taskgroup
:
2809 case OMPD_target_data
:
2810 case OMPD_target_parallel
:
2811 case OMPD_target_parallel_for
:
2813 case OMPD_teams_loop
:
2814 case OMPD_target_teams_loop
:
2815 case OMPD_parallel_loop
:
2816 case OMPD_target_parallel_loop
:
2819 case OMPD_taskloop_simd
:
2820 case OMPD_master_taskloop
:
2821 case OMPD_masked_taskloop
:
2822 case OMPD_master_taskloop_simd
:
2823 case OMPD_masked_taskloop_simd
:
2824 case OMPD_parallel_master_taskloop
:
2825 case OMPD_parallel_masked_taskloop
:
2826 case OMPD_parallel_master_taskloop_simd
:
2827 case OMPD_parallel_masked_taskloop_simd
:
2828 case OMPD_distribute
:
2829 case OMPD_distribute_parallel_for
:
2830 case OMPD_distribute_parallel_for_simd
:
2831 case OMPD_distribute_simd
:
2832 case OMPD_target_parallel_for_simd
:
2833 case OMPD_target_simd
:
2834 case OMPD_teams_distribute
:
2835 case OMPD_teams_distribute_simd
:
2836 case OMPD_teams_distribute_parallel_for_simd
:
2837 case OMPD_teams_distribute_parallel_for
:
2838 case OMPD_target_teams
:
2839 case OMPD_target_teams_distribute
:
2840 case OMPD_target_teams_distribute_parallel_for
:
2841 case OMPD_target_teams_distribute_parallel_for_simd
:
2842 case OMPD_target_teams_distribute_simd
:
2845 // Special processing for flush and depobj clauses.
2847 bool ImplicitClauseAllowed
= false;
2848 if (DKind
== OMPD_flush
|| DKind
== OMPD_depobj
) {
2850 ImplicitClauseAllowed
= true;
2853 // Parse directive name of the 'critical' directive if any.
2854 if (DKind
== OMPD_critical
) {
2855 BalancedDelimiterTracker
T(*this, tok::l_paren
,
2856 tok::annot_pragma_openmp_end
);
2857 if (!T
.consumeOpen()) {
2858 if (Tok
.isAnyIdentifier()) {
2860 DeclarationNameInfo(Tok
.getIdentifierInfo(), Tok
.getLocation());
2863 Diag(Tok
, diag::err_omp_expected_identifier_for_critical
);
2867 } else if (DKind
== OMPD_cancellation_point
|| DKind
== OMPD_cancel
) {
2868 CancelRegion
= parseOpenMPDirectiveKind(*this);
2869 if (Tok
.isNot(tok::annot_pragma_openmp_end
))
2873 if (isOpenMPLoopDirective(DKind
))
2874 ScopeFlags
|= Scope::OpenMPLoopDirectiveScope
;
2875 if (isOpenMPSimdDirective(DKind
))
2876 ScopeFlags
|= Scope::OpenMPSimdDirectiveScope
;
2877 ParseScope
OMPDirectiveScope(this, ScopeFlags
);
2878 Actions
.StartOpenMPDSABlock(DKind
, DirName
, Actions
.getCurScope(), Loc
);
2880 while (Tok
.isNot(tok::annot_pragma_openmp_end
)) {
2881 // If we are parsing for a directive within a metadirective, the directive
2883 if (ReadDirectiveWithinMetadirective
&& Tok
.is(tok::r_paren
)) {
2884 while (Tok
.isNot(tok::annot_pragma_openmp_end
))
2888 bool HasImplicitClause
= false;
2889 if (ImplicitClauseAllowed
&& Tok
.is(tok::l_paren
)) {
2890 HasImplicitClause
= true;
2891 // Push copy of the current token back to stream to properly parse
2892 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2893 PP
.EnterToken(Tok
, /*IsReinject*/ true);
2894 PP
.EnterToken(ImplicitTok
, /*IsReinject*/ true);
2897 OpenMPClauseKind CKind
= Tok
.isAnnotation()
2899 : getOpenMPClauseKind(PP
.getSpelling(Tok
));
2900 if (HasImplicitClause
) {
2901 assert(CKind
== OMPC_unknown
&& "Must be unknown implicit clause.");
2902 if (DKind
== OMPD_flush
) {
2905 assert(DKind
== OMPD_depobj
&&
2906 "Expected flush or depobj directives.");
2907 CKind
= OMPC_depobj
;
2910 // No more implicit clauses allowed.
2911 ImplicitClauseAllowed
= false;
2912 Actions
.StartOpenMPClause(CKind
);
2913 HasImplicitClause
= false;
2914 OMPClause
*Clause
= ParseOpenMPClause(
2915 DKind
, CKind
, !FirstClauses
[unsigned(CKind
)].getInt());
2916 FirstClauses
[unsigned(CKind
)].setInt(true);
2918 FirstClauses
[unsigned(CKind
)].setPointer(Clause
);
2919 Clauses
.push_back(Clause
);
2923 if (Tok
.is(tok::comma
))
2925 Actions
.EndOpenMPClause();
2927 // End location of the directive.
2928 EndLoc
= Tok
.getLocation();
2929 // Consume final annot_pragma_openmp_end.
2930 ConsumeAnnotationToken();
2932 if (DKind
== OMPD_ordered
) {
2933 // If the depend or doacross clause is specified, the ordered construct
2934 // is a stand-alone directive.
2935 for (auto CK
: {OMPC_depend
, OMPC_doacross
}) {
2936 if (FirstClauses
[unsigned(CK
)].getInt()) {
2937 if ((StmtCtx
& ParsedStmtContext::AllowStandaloneOpenMPDirectives
) ==
2938 ParsedStmtContext()) {
2939 Diag(Loc
, diag::err_omp_immediate_directive
)
2940 << getOpenMPDirectiveName(DKind
) << 1
2941 << getOpenMPClauseName(CK
);
2943 HasAssociatedStatement
= false;
2948 if (DKind
== OMPD_tile
&& !FirstClauses
[unsigned(OMPC_sizes
)].getInt()) {
2949 Diag(Loc
, diag::err_omp_required_clause
)
2950 << getOpenMPDirectiveName(OMPD_tile
) << "sizes";
2953 StmtResult AssociatedStmt
;
2954 if (HasAssociatedStatement
) {
2955 // The body is a block scope like in Lambdas and Blocks.
2956 Actions
.ActOnOpenMPRegionStart(DKind
, getCurScope());
2957 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2958 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2959 // should have at least one compound statement scope within it.
2960 ParsingOpenMPDirectiveRAII
NormalScope(*this, /*Value=*/false);
2962 Sema::CompoundScopeRAII
Scope(Actions
);
2963 AssociatedStmt
= ParseStatement();
2965 if (AssociatedStmt
.isUsable() && isOpenMPLoopDirective(DKind
) &&
2966 getLangOpts().OpenMPIRBuilder
)
2967 AssociatedStmt
= Actions
.ActOnOpenMPLoopnest(AssociatedStmt
.get());
2969 AssociatedStmt
= Actions
.ActOnOpenMPRegionEnd(AssociatedStmt
, Clauses
);
2970 } else if (DKind
== OMPD_target_update
|| DKind
== OMPD_target_enter_data
||
2971 DKind
== OMPD_target_exit_data
) {
2972 Actions
.ActOnOpenMPRegionStart(DKind
, getCurScope());
2973 AssociatedStmt
= (Sema::CompoundScopeRAII(Actions
),
2974 Actions
.ActOnCompoundStmt(Loc
, Loc
, std::nullopt
,
2975 /*isStmtExpr=*/false));
2976 AssociatedStmt
= Actions
.ActOnOpenMPRegionEnd(AssociatedStmt
, Clauses
);
2978 Directive
= Actions
.ActOnOpenMPExecutableDirective(
2979 DKind
, DirName
, CancelRegion
, Clauses
, AssociatedStmt
.get(), Loc
,
2983 Actions
.EndOpenMPDSABlock(Directive
.get());
2984 OMPDirectiveScope
.Exit();
2987 case OMPD_declare_simd
:
2988 case OMPD_declare_target
:
2989 case OMPD_begin_declare_target
:
2990 case OMPD_end_declare_target
:
2992 case OMPD_begin_declare_variant
:
2993 case OMPD_end_declare_variant
:
2994 case OMPD_declare_variant
:
2995 Diag(Tok
, diag::err_omp_unexpected_directive
)
2996 << 1 << getOpenMPDirectiveName(DKind
);
2997 SkipUntil(tok::annot_pragma_openmp_end
);
3001 Diag(Tok
, diag::err_omp_unknown_directive
);
3002 SkipUntil(tok::annot_pragma_openmp_end
);
3008 // Parses simple list:
3009 // simple-variable-list:
3010 // '(' id-expression {, id-expression} ')'
3012 bool Parser::ParseOpenMPSimpleVarList(
3013 OpenMPDirectiveKind Kind
,
3014 const llvm::function_ref
<void(CXXScopeSpec
&, DeclarationNameInfo
)>
3016 bool AllowScopeSpecifier
) {
3018 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
3019 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
3020 getOpenMPDirectiveName(Kind
).data()))
3022 bool IsCorrect
= true;
3023 bool NoIdentIsFound
= true;
3025 // Read tokens while ')' or annot_pragma_openmp_end is not found.
3026 while (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::annot_pragma_openmp_end
)) {
3030 Token PrevTok
= Tok
;
3031 NoIdentIsFound
= false;
3033 if (AllowScopeSpecifier
&& getLangOpts().CPlusPlus
&&
3034 ParseOptionalCXXScopeSpecifier(SS
, /*ObjectType=*/nullptr,
3035 /*ObjectHasErrors=*/false, false)) {
3037 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
3039 } else if (ParseUnqualifiedId(SS
, /*ObjectType=*/nullptr,
3040 /*ObjectHadErrors=*/false, false, false,
3041 false, false, nullptr, Name
)) {
3043 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
3045 } else if (Tok
.isNot(tok::comma
) && Tok
.isNot(tok::r_paren
) &&
3046 Tok
.isNot(tok::annot_pragma_openmp_end
)) {
3048 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
3050 Diag(PrevTok
.getLocation(), diag::err_expected
)
3052 << SourceRange(PrevTok
.getLocation(), PrevTokLocation
);
3054 Callback(SS
, Actions
.GetNameFromUnqualifiedId(Name
));
3057 if (Tok
.is(tok::comma
)) {
3062 if (NoIdentIsFound
) {
3063 Diag(Tok
, diag::err_expected
) << tok::identifier
;
3068 IsCorrect
= !T
.consumeClose() && IsCorrect
;
3073 OMPClause
*Parser::ParseOpenMPSizesClause() {
3074 SourceLocation ClauseNameLoc
= ConsumeToken();
3075 SmallVector
<Expr
*, 4> ValExprs
;
3077 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
3078 if (T
.consumeOpen()) {
3079 Diag(Tok
, diag::err_expected
) << tok::l_paren
;
3084 ExprResult Val
= ParseConstantExpression();
3085 if (!Val
.isUsable()) {
3090 ValExprs
.push_back(Val
.get());
3092 if (Tok
.is(tok::r_paren
) || Tok
.is(tok::annot_pragma_openmp_end
))
3095 ExpectAndConsume(tok::comma
);
3100 return Actions
.ActOnOpenMPSizesClause(
3101 ValExprs
, ClauseNameLoc
, T
.getOpenLocation(), T
.getCloseLocation());
3104 OMPClause
*Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind
) {
3105 SourceLocation Loc
= Tok
.getLocation();
3109 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
3110 if (T
.expectAndConsume(diag::err_expected_lparen_after
, "uses_allocator"))
3112 SmallVector
<Sema::UsesAllocatorsData
, 4> Data
;
3116 ExprResult Allocator
=
3117 getLangOpts().CPlusPlus
3118 ? ParseCXXIdExpression()
3119 : tryParseCXXIdExpression(SS
, /*isAddressOfOperand=*/false,
3121 if (Allocator
.isInvalid()) {
3122 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
3126 Sema::UsesAllocatorsData
&D
= Data
.emplace_back();
3127 D
.Allocator
= Allocator
.get();
3128 if (Tok
.is(tok::l_paren
)) {
3129 BalancedDelimiterTracker
T(*this, tok::l_paren
,
3130 tok::annot_pragma_openmp_end
);
3132 ExprResult AllocatorTraits
=
3133 getLangOpts().CPlusPlus
? ParseCXXIdExpression() : ParseExpression();
3135 if (AllocatorTraits
.isInvalid()) {
3136 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
3140 D
.AllocatorTraits
= AllocatorTraits
.get();
3141 D
.LParenLoc
= T
.getOpenLocation();
3142 D
.RParenLoc
= T
.getCloseLocation();
3144 if (Tok
.isNot(tok::comma
) && Tok
.isNot(tok::r_paren
))
3145 Diag(Tok
, diag::err_omp_expected_punc
) << "uses_allocators" << 0;
3147 if (Tok
.is(tok::comma
))
3149 } while (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::annot_pragma_openmp_end
));
3151 return Actions
.ActOnOpenMPUsesAllocatorClause(Loc
, T
.getOpenLocation(),
3152 T
.getCloseLocation(), Data
);
3155 /// Parsing of OpenMP clauses.
3158 /// if-clause | final-clause | num_threads-clause | safelen-clause |
3159 /// default-clause | private-clause | firstprivate-clause | shared-clause
3160 /// | linear-clause | aligned-clause | collapse-clause | bind-clause |
3161 /// lastprivate-clause | reduction-clause | proc_bind-clause |
3162 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
3163 /// mergeable-clause | flush-clause | read-clause | write-clause |
3164 /// update-clause | capture-clause | seq_cst-clause | device-clause |
3165 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
3166 /// thread_limit-clause | priority-clause | grainsize-clause |
3167 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
3168 /// from-clause | is_device_ptr-clause | task_reduction-clause |
3169 /// in_reduction-clause | allocator-clause | allocate-clause |
3170 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
3171 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause |
3172 /// exclusive-clause | uses_allocators-clause | use_device_addr-clause |
3175 OMPClause
*Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind
,
3176 OpenMPClauseKind CKind
, bool FirstClause
) {
3177 OMPClauseKind
= CKind
;
3178 OMPClause
*Clause
= nullptr;
3179 bool ErrorFound
= false;
3180 bool WrongDirective
= false;
3181 // Check if clause is allowed for the given directive.
3182 if (CKind
!= OMPC_unknown
&&
3183 !isAllowedClauseForDirective(DKind
, CKind
, getLangOpts().OpenMP
)) {
3184 Diag(Tok
, diag::err_omp_unexpected_clause
)
3185 << getOpenMPClauseName(CKind
) << getOpenMPDirectiveName(DKind
);
3187 WrongDirective
= true;
3192 case OMPC_num_threads
:
3197 case OMPC_num_teams
:
3198 case OMPC_thread_limit
:
3200 case OMPC_grainsize
:
3201 case OMPC_num_tasks
:
3203 case OMPC_allocator
:
3206 case OMPC_novariants
:
3207 case OMPC_nocontext
:
3212 case OMPC_ompx_dyn_cgroup_mem
:
3213 // OpenMP [2.5, Restrictions]
3214 // At most one num_threads clause can appear on the directive.
3215 // OpenMP [2.8.1, simd construct, Restrictions]
3216 // Only one safelen clause can appear on a simd directive.
3217 // Only one simdlen clause can appear on a simd directive.
3218 // Only one collapse clause can appear on a simd directive.
3219 // OpenMP [2.11.1, task Construct, Restrictions]
3220 // At most one if clause can appear on the directive.
3221 // At most one final clause can appear on the directive.
3222 // OpenMP [teams Construct, Restrictions]
3223 // At most one num_teams clause can appear on the directive.
3224 // At most one thread_limit clause can appear on the directive.
3225 // OpenMP [2.9.1, task Construct, Restrictions]
3226 // At most one priority clause can appear on the directive.
3227 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3228 // At most one grainsize clause can appear on the directive.
3229 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3230 // At most one num_tasks clause can appear on the directive.
3231 // OpenMP [2.11.3, allocate Directive, Restrictions]
3232 // At most one allocator clause can appear on the directive.
3233 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3234 // At most one detach clause can appear on the directive.
3235 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3236 // At most one novariants clause can appear on a dispatch directive.
3237 // At most one nocontext clause can appear on a dispatch directive.
3238 // OpenMP [5.1, error directive, Restrictions]
3239 // At most one message clause can appear on the directive
3241 Diag(Tok
, diag::err_omp_more_one_clause
)
3242 << getOpenMPDirectiveName(DKind
) << getOpenMPClauseName(CKind
) << 0;
3246 if ((CKind
== OMPC_ordered
|| CKind
== OMPC_partial
) &&
3247 PP
.LookAhead(/*N=*/0).isNot(tok::l_paren
))
3248 Clause
= ParseOpenMPClause(CKind
, WrongDirective
);
3249 else if (CKind
== OMPC_grainsize
|| CKind
== OMPC_num_tasks
)
3250 Clause
= ParseOpenMPSingleExprWithArgClause(DKind
, CKind
, WrongDirective
);
3252 Clause
= ParseOpenMPSingleExprClause(CKind
, WrongDirective
);
3256 case OMPC_proc_bind
:
3257 case OMPC_atomic_default_mem_order
:
3261 // OpenMP [2.14.3.1, Restrictions]
3262 // Only a single default clause may be specified on a parallel, task or
3264 // OpenMP [2.5, parallel Construct, Restrictions]
3265 // At most one proc_bind clause can appear on the directive.
3266 // OpenMP [5.0, Requires directive, Restrictions]
3267 // At most one atomic_default_mem_order clause can appear
3269 // OpenMP [5.1, error directive, Restrictions]
3270 // At most one at clause can appear on the directive
3271 // At most one severity clause can appear on the directive
3272 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3273 // At most one bind clause can appear on a loop directive.
3275 Diag(Tok
, diag::err_omp_more_one_clause
)
3276 << getOpenMPDirectiveName(DKind
) << getOpenMPClauseName(CKind
) << 0;
3280 Clause
= ParseOpenMPSimpleClause(CKind
, WrongDirective
);
3284 case OMPC_dist_schedule
:
3285 case OMPC_defaultmap
:
3287 // OpenMP [2.7.1, Restrictions, p. 3]
3288 // Only one schedule clause can appear on a loop directive.
3289 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3290 // At most one defaultmap clause can appear on the directive.
3291 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3292 // At most one device clause can appear on the directive.
3293 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3294 // At most one order clause may appear on a construct.
3295 if ((getLangOpts().OpenMP
< 50 || CKind
!= OMPC_defaultmap
) &&
3296 (CKind
!= OMPC_order
|| getLangOpts().OpenMP
>= 51) && !FirstClause
) {
3297 Diag(Tok
, diag::err_omp_more_one_clause
)
3298 << getOpenMPDirectiveName(DKind
) << getOpenMPClauseName(CKind
) << 0;
3303 Clause
= ParseOpenMPSingleExprWithArgClause(DKind
, CKind
, WrongDirective
);
3307 case OMPC_mergeable
:
3320 case OMPC_unified_address
:
3321 case OMPC_unified_shared_memory
:
3322 case OMPC_reverse_offload
:
3323 case OMPC_dynamic_allocators
:
3325 // OpenMP [2.7.1, Restrictions, p. 9]
3326 // Only one ordered clause can appear on a loop directive.
3327 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3328 // Only one nowait clause can appear on a for directive.
3329 // OpenMP [5.0, Requires directive, Restrictions]
3330 // Each of the requires clauses can appear at most once on the directive.
3332 Diag(Tok
, diag::err_omp_more_one_clause
)
3333 << getOpenMPDirectiveName(DKind
) << getOpenMPClauseName(CKind
) << 0;
3337 Clause
= ParseOpenMPClause(CKind
, WrongDirective
);
3341 Diag(Tok
, diag::err_omp_more_one_clause
)
3342 << getOpenMPDirectiveName(DKind
) << getOpenMPClauseName(CKind
) << 0;
3346 Clause
= (DKind
== OMPD_depobj
)
3347 ? ParseOpenMPSimpleClause(CKind
, WrongDirective
)
3348 : ParseOpenMPClause(CKind
, WrongDirective
);
3351 case OMPC_firstprivate
:
3352 case OMPC_lastprivate
:
3354 case OMPC_reduction
:
3355 case OMPC_task_reduction
:
3356 case OMPC_in_reduction
:
3360 case OMPC_copyprivate
:
3366 case OMPC_use_device_ptr
:
3367 case OMPC_use_device_addr
:
3368 case OMPC_is_device_ptr
:
3369 case OMPC_has_device_addr
:
3371 case OMPC_nontemporal
:
3372 case OMPC_inclusive
:
3373 case OMPC_exclusive
:
3377 if (getLangOpts().OpenMP
>= 52 && DKind
== OMPD_ordered
&&
3378 CKind
== OMPC_depend
)
3379 Diag(Tok
, diag::warn_omp_depend_in_ordered_deprecated
);
3380 Clause
= ParseOpenMPVarListClause(DKind
, CKind
, WrongDirective
);
3384 Diag(Tok
, diag::err_omp_more_one_clause
)
3385 << getOpenMPDirectiveName(DKind
) << getOpenMPClauseName(CKind
) << 0;
3389 Clause
= ParseOpenMPSizesClause();
3391 case OMPC_uses_allocators
:
3392 Clause
= ParseOpenMPUsesAllocatorClause(DKind
);
3395 if (DKind
!= OMPD_interop
) {
3397 Diag(Tok
, diag::err_omp_more_one_clause
)
3398 << getOpenMPDirectiveName(DKind
) << getOpenMPClauseName(CKind
) << 0;
3401 Clause
= ParseOpenMPClause(CKind
, WrongDirective
);
3407 Clause
= ParseOpenMPInteropClause(CKind
, WrongDirective
);
3409 case OMPC_device_type
:
3411 skipUntilPragmaOpenMPEnd(DKind
);
3413 case OMPC_threadprivate
:
3416 if (!WrongDirective
)
3417 Diag(Tok
, diag::err_omp_unexpected_clause
)
3418 << getOpenMPClauseName(CKind
) << getOpenMPDirectiveName(DKind
);
3419 SkipUntil(tok::comma
, tok::annot_pragma_openmp_end
, StopBeforeMatch
);
3421 case OMPC_ompx_attribute
:
3422 Clause
= ParseOpenMPOMPXAttributesClause(WrongDirective
);
3424 case OMPC_ompx_bare
:
3426 Diag(Tok
, diag::note_ompx_bare_clause
)
3427 << getOpenMPClauseName(CKind
) << "target teams";
3428 if (!ErrorFound
&& !getLangOpts().OpenMPExtensions
) {
3429 Diag(Tok
, diag::err_omp_unexpected_clause_extension_only
)
3430 << getOpenMPClauseName(CKind
) << getOpenMPDirectiveName(DKind
);
3433 Clause
= ParseOpenMPClause(CKind
, WrongDirective
);
3438 return ErrorFound
? nullptr : Clause
;
3441 /// Parses simple expression in parens for single-expression clauses of OpenMP
3443 /// \param RLoc Returned location of right paren.
3444 ExprResult
Parser::ParseOpenMPParensExpr(StringRef ClauseName
,
3445 SourceLocation
&RLoc
,
3446 bool IsAddressOfOperand
) {
3447 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
3448 if (T
.expectAndConsume(diag::err_expected_lparen_after
, ClauseName
.data()))
3451 SourceLocation ELoc
= Tok
.getLocation();
3453 ParseCastExpression(AnyCastExpr
, IsAddressOfOperand
, NotTypeCast
));
3454 ExprResult
Val(ParseRHSOfBinaryExpression(LHS
, prec::Conditional
));
3455 Val
= Actions
.ActOnFinishFullExpr(Val
.get(), ELoc
, /*DiscardedValue*/ false);
3458 RLoc
= Tok
.getLocation();
3459 if (!T
.consumeClose())
3460 RLoc
= T
.getCloseLocation();
3465 /// Parsing of OpenMP clauses with single expressions like 'final',
3466 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
3467 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
3471 /// 'final' '(' expression ')'
3473 /// num_threads-clause:
3474 /// 'num_threads' '(' expression ')'
3477 /// 'safelen' '(' expression ')'
3480 /// 'simdlen' '(' expression ')'
3482 /// collapse-clause:
3483 /// 'collapse' '(' expression ')'
3485 /// priority-clause:
3486 /// 'priority' '(' expression ')'
3488 /// grainsize-clause:
3489 /// 'grainsize' '(' expression ')'
3491 /// num_tasks-clause:
3492 /// 'num_tasks' '(' expression ')'
3495 /// 'hint' '(' expression ')'
3497 /// allocator-clause:
3498 /// 'allocator' '(' expression ')'
3501 /// 'detach' '(' event-handler-expression ')'
3504 /// 'align' '(' positive-integer-constant ')'
3506 OMPClause
*Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind
,
3508 SourceLocation Loc
= ConsumeToken();
3509 SourceLocation LLoc
= Tok
.getLocation();
3510 SourceLocation RLoc
;
3512 ExprResult Val
= ParseOpenMPParensExpr(getOpenMPClauseName(Kind
), RLoc
);
3514 if (Val
.isInvalid())
3519 return Actions
.ActOnOpenMPSingleExprClause(Kind
, Val
.get(), Loc
, LLoc
, RLoc
);
3522 /// Parse indirect clause for '#pragma omp declare target' directive.
3523 /// 'indirect' '[' '(' invoked-by-fptr ')' ']'
3524 /// where invoked-by-fptr is a constant boolean expression that evaluates to
3525 /// true or false at compile time.
3526 bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo
&DTCI
,
3528 SourceLocation Loc
= ConsumeToken();
3529 SourceLocation RLoc
;
3531 if (Tok
.isNot(tok::l_paren
)) {
3534 DTCI
.Indirect
= nullptr;
3539 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect
), RLoc
);
3540 if (Val
.isInvalid())
3546 if (!Val
.get()->isValueDependent() && !Val
.get()->isTypeDependent() &&
3547 !Val
.get()->isInstantiationDependent() &&
3548 !Val
.get()->containsUnexpandedParameterPack()) {
3549 ExprResult Ret
= Actions
.CheckBooleanCondition(Loc
, Val
.get());
3550 if (Ret
.isInvalid())
3552 llvm::APSInt Result
;
3553 Ret
= Actions
.VerifyIntegerConstantExpression(Val
.get(), &Result
,
3555 if (Ret
.isInvalid())
3557 DTCI
.Indirect
= Val
.get();
3563 /// Parses a comma-separated list of interop-types and a prefer_type list.
3565 bool Parser::ParseOMPInteropInfo(OMPInteropInfo
&InteropInfo
,
3566 OpenMPClauseKind Kind
) {
3567 const Token
&Tok
= getCurToken();
3568 bool HasError
= false;
3569 bool IsTarget
= false;
3570 bool IsTargetSync
= false;
3572 while (Tok
.is(tok::identifier
)) {
3573 // Currently prefer_type is only allowed with 'init' and it must be first.
3574 bool PreferTypeAllowed
= Kind
== OMPC_init
&&
3575 InteropInfo
.PreferTypes
.empty() && !IsTarget
&&
3577 if (Tok
.getIdentifierInfo()->isStr("target")) {
3578 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3579 // Each interop-type may be specified on an action-clause at most
3582 Diag(Tok
, diag::warn_omp_more_one_interop_type
) << "target";
3585 } else if (Tok
.getIdentifierInfo()->isStr("targetsync")) {
3587 Diag(Tok
, diag::warn_omp_more_one_interop_type
) << "targetsync";
3588 IsTargetSync
= true;
3590 } else if (Tok
.getIdentifierInfo()->isStr("prefer_type") &&
3591 PreferTypeAllowed
) {
3593 BalancedDelimiterTracker
PT(*this, tok::l_paren
,
3594 tok::annot_pragma_openmp_end
);
3595 if (PT
.expectAndConsume(diag::err_expected_lparen_after
, "prefer_type"))
3598 while (Tok
.isNot(tok::r_paren
)) {
3599 SourceLocation Loc
= Tok
.getLocation();
3600 ExprResult LHS
= ParseCastExpression(AnyCastExpr
);
3601 ExprResult PTExpr
= Actions
.CorrectDelayedTyposInExpr(
3602 ParseRHSOfBinaryExpression(LHS
, prec::Conditional
));
3603 PTExpr
= Actions
.ActOnFinishFullExpr(PTExpr
.get(), Loc
,
3604 /*DiscardedValue=*/false);
3605 if (PTExpr
.isUsable()) {
3606 InteropInfo
.PreferTypes
.push_back(PTExpr
.get());
3609 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
3613 if (Tok
.is(tok::comma
))
3619 Diag(Tok
, diag::err_omp_expected_interop_type
);
3622 if (!Tok
.is(tok::comma
))
3627 if (!HasError
&& !IsTarget
&& !IsTargetSync
) {
3628 Diag(Tok
, diag::err_omp_expected_interop_type
);
3632 if (Kind
== OMPC_init
) {
3633 if (Tok
.isNot(tok::colon
) && (IsTarget
|| IsTargetSync
))
3634 Diag(Tok
, diag::warn_pragma_expected_colon
) << "interop types";
3635 if (Tok
.is(tok::colon
))
3639 // As of OpenMP 5.1,there are two interop-types, "target" and
3640 // "targetsync". Either or both are allowed for a single interop.
3641 InteropInfo
.IsTarget
= IsTarget
;
3642 InteropInfo
.IsTargetSync
= IsTargetSync
;
3647 /// Parsing of OpenMP clauses that use an interop-var.
3650 /// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
3653 /// destroy(interop-var)
3656 /// use(interop-var)
3658 /// interop-modifier:
3659 /// prefer_type(preference-list)
3661 /// preference-list:
3662 /// foreign-runtime-id [, foreign-runtime-id]...
3664 /// foreign-runtime-id:
3665 /// <string-literal> | <constant-integral-expression>
3668 /// target | targetsync
3670 OMPClause
*Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind
,
3672 SourceLocation Loc
= ConsumeToken();
3674 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
3675 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
3676 getOpenMPClauseName(Kind
).data()))
3679 bool InteropError
= false;
3680 OMPInteropInfo InteropInfo
;
3681 if (Kind
== OMPC_init
)
3682 InteropError
= ParseOMPInteropInfo(InteropInfo
, OMPC_init
);
3684 // Parse the variable.
3685 SourceLocation VarLoc
= Tok
.getLocation();
3686 ExprResult InteropVarExpr
=
3687 Actions
.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3688 if (!InteropVarExpr
.isUsable()) {
3689 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
3694 SourceLocation RLoc
= Tok
.getLocation();
3695 if (!T
.consumeClose())
3696 RLoc
= T
.getCloseLocation();
3698 if (ParseOnly
|| !InteropVarExpr
.isUsable() || InteropError
)
3701 if (Kind
== OMPC_init
)
3702 return Actions
.ActOnOpenMPInitClause(InteropVarExpr
.get(), InteropInfo
, Loc
,
3703 T
.getOpenLocation(), VarLoc
, RLoc
);
3704 if (Kind
== OMPC_use
)
3705 return Actions
.ActOnOpenMPUseClause(InteropVarExpr
.get(), Loc
,
3706 T
.getOpenLocation(), VarLoc
, RLoc
);
3708 if (Kind
== OMPC_destroy
)
3709 return Actions
.ActOnOpenMPDestroyClause(InteropVarExpr
.get(), Loc
,
3710 T
.getOpenLocation(), VarLoc
, RLoc
);
3712 llvm_unreachable("Unexpected interop variable clause.");
3715 OMPClause
*Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly
) {
3716 SourceLocation Loc
= ConsumeToken();
3718 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
3719 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
3720 getOpenMPClauseName(OMPC_ompx_attribute
).data()))
3723 ParsedAttributes
ParsedAttrs(AttrFactory
);
3724 ParseAttributes(PAKM_GNU
| PAKM_CXX11
, ParsedAttrs
);
3727 if (T
.consumeClose())
3733 SmallVector
<Attr
*> Attrs
;
3734 for (const ParsedAttr
&PA
: ParsedAttrs
) {
3735 switch (PA
.getKind()) {
3736 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize
:
3737 if (!PA
.checkExactlyNumArgs(Actions
, 2))
3739 if (auto *A
= Actions
.CreateAMDGPUFlatWorkGroupSizeAttr(
3740 PA
, PA
.getArgAsExpr(0), PA
.getArgAsExpr(1)))
3743 case ParsedAttr::AT_AMDGPUWavesPerEU
:
3744 if (!PA
.checkAtLeastNumArgs(Actions
, 1) ||
3745 !PA
.checkAtMostNumArgs(Actions
, 2))
3747 if (auto *A
= Actions
.CreateAMDGPUWavesPerEUAttr(
3748 PA
, PA
.getArgAsExpr(0),
3749 PA
.getNumArgs() > 1 ? PA
.getArgAsExpr(1) : nullptr))
3752 case ParsedAttr::AT_CUDALaunchBounds
:
3753 if (!PA
.checkAtLeastNumArgs(Actions
, 1) ||
3754 !PA
.checkAtMostNumArgs(Actions
, 2))
3756 if (auto *A
= Actions
.CreateLaunchBoundsAttr(
3757 PA
, PA
.getArgAsExpr(0),
3758 PA
.getNumArgs() > 1 ? PA
.getArgAsExpr(1) : nullptr,
3759 PA
.getNumArgs() > 2 ? PA
.getArgAsExpr(2) : nullptr))
3763 Diag(Loc
, diag::warn_omp_invalid_attribute_for_ompx_attributes
) << PA
;
3768 return Actions
.ActOnOpenMPXAttributeClause(Attrs
, Loc
, T
.getOpenLocation(),
3769 T
.getCloseLocation());
3772 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
3775 /// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')'
3777 /// proc_bind-clause:
3778 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')'
3781 /// 'bind' '(' 'teams' | 'parallel' | 'thread' ')'
3784 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' |
3787 OMPClause
*Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind
,
3789 std::optional
<SimpleClauseData
> Val
= parseOpenMPSimpleClause(*this, Kind
);
3790 if (!Val
|| ParseOnly
)
3792 if (getLangOpts().OpenMP
< 51 && Kind
== OMPC_default
&&
3793 (static_cast<DefaultKind
>(Val
->Type
) == OMP_DEFAULT_private
||
3794 static_cast<DefaultKind
>(Val
->Type
) ==
3795 OMP_DEFAULT_firstprivate
)) {
3796 Diag(Val
->LOpen
, diag::err_omp_invalid_dsa
)
3797 << getOpenMPClauseName(static_cast<DefaultKind
>(Val
->Type
) ==
3800 : OMPC_firstprivate
)
3801 << getOpenMPClauseName(OMPC_default
) << "5.1";
3804 return Actions
.ActOnOpenMPSimpleClause(Kind
, Val
->Type
,
3805 Val
->TypeLoc
, Val
->LOpen
,
3806 Val
->Loc
, Val
->RLoc
);
3809 /// Parsing of OpenMP clauses like 'ordered'.
3820 /// mergeable-clause:
3835 OMPClause
*Parser::ParseOpenMPClause(OpenMPClauseKind Kind
, bool ParseOnly
) {
3836 SourceLocation Loc
= Tok
.getLocation();
3841 return Actions
.ActOnOpenMPClause(Kind
, Loc
, Tok
.getLocation());
3844 /// Parsing of OpenMP clauses with single expressions and some additional
3845 /// argument like 'schedule' or 'dist_schedule'.
3847 /// schedule-clause:
3848 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
3852 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
3855 /// 'defaultmap' '(' modifier [ ':' kind ] ')'
3858 /// 'device' '(' [ device-modifier ':' ] expression ')'
3860 OMPClause
*Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind
,
3861 OpenMPClauseKind Kind
,
3863 SourceLocation Loc
= ConsumeToken();
3864 SourceLocation DelimLoc
;
3866 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
3867 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
3868 getOpenMPClauseName(Kind
).data()))
3872 SmallVector
<unsigned, 4> Arg
;
3873 SmallVector
<SourceLocation
, 4> KLoc
;
3874 if (Kind
== OMPC_schedule
) {
3875 enum { Modifier1
, Modifier2
, ScheduleKind
, NumberOfElements
};
3876 Arg
.resize(NumberOfElements
);
3877 KLoc
.resize(NumberOfElements
);
3878 Arg
[Modifier1
] = OMPC_SCHEDULE_MODIFIER_unknown
;
3879 Arg
[Modifier2
] = OMPC_SCHEDULE_MODIFIER_unknown
;
3880 Arg
[ScheduleKind
] = OMPC_SCHEDULE_unknown
;
3881 unsigned KindModifier
= getOpenMPSimpleClauseType(
3882 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts());
3883 if (KindModifier
> OMPC_SCHEDULE_unknown
) {
3885 Arg
[Modifier1
] = KindModifier
;
3886 KLoc
[Modifier1
] = Tok
.getLocation();
3887 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3888 Tok
.isNot(tok::annot_pragma_openmp_end
))
3890 if (Tok
.is(tok::comma
)) {
3891 // Parse ',' 'modifier'
3893 KindModifier
= getOpenMPSimpleClauseType(
3894 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts());
3895 Arg
[Modifier2
] = KindModifier
> OMPC_SCHEDULE_unknown
3897 : (unsigned)OMPC_SCHEDULE_unknown
;
3898 KLoc
[Modifier2
] = Tok
.getLocation();
3899 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3900 Tok
.isNot(tok::annot_pragma_openmp_end
))
3904 if (Tok
.is(tok::colon
))
3907 Diag(Tok
, diag::warn_pragma_expected_colon
) << "schedule modifier";
3908 KindModifier
= getOpenMPSimpleClauseType(
3909 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts());
3911 Arg
[ScheduleKind
] = KindModifier
;
3912 KLoc
[ScheduleKind
] = Tok
.getLocation();
3913 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3914 Tok
.isNot(tok::annot_pragma_openmp_end
))
3916 if ((Arg
[ScheduleKind
] == OMPC_SCHEDULE_static
||
3917 Arg
[ScheduleKind
] == OMPC_SCHEDULE_dynamic
||
3918 Arg
[ScheduleKind
] == OMPC_SCHEDULE_guided
) &&
3920 DelimLoc
= ConsumeAnyToken();
3921 } else if (Kind
== OMPC_dist_schedule
) {
3922 Arg
.push_back(getOpenMPSimpleClauseType(
3923 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts()));
3924 KLoc
.push_back(Tok
.getLocation());
3925 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3926 Tok
.isNot(tok::annot_pragma_openmp_end
))
3928 if (Arg
.back() == OMPC_DIST_SCHEDULE_static
&& Tok
.is(tok::comma
))
3929 DelimLoc
= ConsumeAnyToken();
3930 } else if (Kind
== OMPC_defaultmap
) {
3931 // Get a defaultmap modifier
3932 unsigned Modifier
= getOpenMPSimpleClauseType(
3933 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts());
3934 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3936 if (Modifier
< OMPC_DEFAULTMAP_MODIFIER_unknown
)
3937 Modifier
= OMPC_DEFAULTMAP_MODIFIER_unknown
;
3938 Arg
.push_back(Modifier
);
3939 KLoc
.push_back(Tok
.getLocation());
3940 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3941 Tok
.isNot(tok::annot_pragma_openmp_end
))
3944 if (Tok
.is(tok::colon
) || getLangOpts().OpenMP
< 50) {
3945 if (Tok
.is(tok::colon
))
3947 else if (Arg
.back() != OMPC_DEFAULTMAP_MODIFIER_unknown
)
3948 Diag(Tok
, diag::warn_pragma_expected_colon
) << "defaultmap modifier";
3949 // Get a defaultmap kind
3950 Arg
.push_back(getOpenMPSimpleClauseType(
3951 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts()));
3952 KLoc
.push_back(Tok
.getLocation());
3953 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3954 Tok
.isNot(tok::annot_pragma_openmp_end
))
3957 Arg
.push_back(OMPC_DEFAULTMAP_unknown
);
3958 KLoc
.push_back(SourceLocation());
3960 } else if (Kind
== OMPC_order
) {
3961 enum { Modifier
, OrderKind
, NumberOfElements
};
3962 Arg
.resize(NumberOfElements
);
3963 KLoc
.resize(NumberOfElements
);
3964 Arg
[Modifier
] = OMPC_ORDER_MODIFIER_unknown
;
3965 Arg
[OrderKind
] = OMPC_ORDER_unknown
;
3966 unsigned KindModifier
= getOpenMPSimpleClauseType(
3967 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts());
3968 if (KindModifier
> OMPC_ORDER_unknown
) {
3970 Arg
[Modifier
] = KindModifier
;
3971 KLoc
[Modifier
] = Tok
.getLocation();
3972 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3973 Tok
.isNot(tok::annot_pragma_openmp_end
))
3976 if (Tok
.is(tok::colon
))
3979 Diag(Tok
, diag::warn_pragma_expected_colon
) << "order modifier";
3980 KindModifier
= getOpenMPSimpleClauseType(
3981 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts());
3983 Arg
[OrderKind
] = KindModifier
;
3984 KLoc
[OrderKind
] = Tok
.getLocation();
3985 if (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::comma
) &&
3986 Tok
.isNot(tok::annot_pragma_openmp_end
))
3988 } else if (Kind
== OMPC_device
) {
3989 // Only target executable directives support extended device construct.
3990 if (isOpenMPTargetExecutionDirective(DKind
) && getLangOpts().OpenMP
>= 50 &&
3991 NextToken().is(tok::colon
)) {
3992 // Parse optional <device modifier> ':'
3993 Arg
.push_back(getOpenMPSimpleClauseType(
3994 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
), getLangOpts()));
3995 KLoc
.push_back(Tok
.getLocation());
4000 Arg
.push_back(OMPC_DEVICE_unknown
);
4001 KLoc
.emplace_back();
4003 } else if (Kind
== OMPC_grainsize
) {
4004 // Parse optional <grainsize modifier> ':'
4005 OpenMPGrainsizeClauseModifier Modifier
=
4006 static_cast<OpenMPGrainsizeClauseModifier
>(getOpenMPSimpleClauseType(
4007 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
),
4009 if (getLangOpts().OpenMP
>= 51) {
4010 if (NextToken().is(tok::colon
)) {
4011 Arg
.push_back(Modifier
);
4012 KLoc
.push_back(Tok
.getLocation());
4018 if (Modifier
== OMPC_GRAINSIZE_strict
) {
4019 Diag(Tok
, diag::err_modifier_expected_colon
) << "strict";
4023 Arg
.push_back(OMPC_GRAINSIZE_unknown
);
4024 KLoc
.emplace_back();
4027 Arg
.push_back(OMPC_GRAINSIZE_unknown
);
4028 KLoc
.emplace_back();
4030 } else if (Kind
== OMPC_num_tasks
) {
4031 // Parse optional <num_tasks modifier> ':'
4032 OpenMPNumTasksClauseModifier Modifier
=
4033 static_cast<OpenMPNumTasksClauseModifier
>(getOpenMPSimpleClauseType(
4034 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
),
4036 if (getLangOpts().OpenMP
>= 51) {
4037 if (NextToken().is(tok::colon
)) {
4038 Arg
.push_back(Modifier
);
4039 KLoc
.push_back(Tok
.getLocation());
4045 if (Modifier
== OMPC_NUMTASKS_strict
) {
4046 Diag(Tok
, diag::err_modifier_expected_colon
) << "strict";
4050 Arg
.push_back(OMPC_NUMTASKS_unknown
);
4051 KLoc
.emplace_back();
4054 Arg
.push_back(OMPC_NUMTASKS_unknown
);
4055 KLoc
.emplace_back();
4058 assert(Kind
== OMPC_if
);
4059 KLoc
.push_back(Tok
.getLocation());
4060 TentativeParsingAction
TPA(*this);
4061 auto DK
= parseOpenMPDirectiveKind(*this);
4063 if (DK
!= OMPD_unknown
) {
4065 if (Tok
.is(tok::colon
) && getLangOpts().OpenMP
> 40) {
4067 DelimLoc
= ConsumeToken();
4070 Arg
.back() = unsigned(OMPD_unknown
);
4077 bool NeedAnExpression
= (Kind
== OMPC_schedule
&& DelimLoc
.isValid()) ||
4078 (Kind
== OMPC_dist_schedule
&& DelimLoc
.isValid()) ||
4079 Kind
== OMPC_if
|| Kind
== OMPC_device
||
4080 Kind
== OMPC_grainsize
|| Kind
== OMPC_num_tasks
;
4081 if (NeedAnExpression
) {
4082 SourceLocation ELoc
= Tok
.getLocation();
4083 ExprResult
LHS(ParseCastExpression(AnyCastExpr
, false, NotTypeCast
));
4084 Val
= ParseRHSOfBinaryExpression(LHS
, prec::Conditional
);
4086 Actions
.ActOnFinishFullExpr(Val
.get(), ELoc
, /*DiscardedValue*/ false);
4090 SourceLocation RLoc
= Tok
.getLocation();
4091 if (!T
.consumeClose())
4092 RLoc
= T
.getCloseLocation();
4094 if (NeedAnExpression
&& Val
.isInvalid())
4099 return Actions
.ActOnOpenMPSingleExprWithArgClause(
4100 Kind
, Arg
, Val
.get(), Loc
, T
.getOpenLocation(), KLoc
, DelimLoc
, RLoc
);
4103 static bool ParseReductionId(Parser
&P
, CXXScopeSpec
&ReductionIdScopeSpec
,
4104 UnqualifiedId
&ReductionId
) {
4105 if (ReductionIdScopeSpec
.isEmpty()) {
4107 switch (P
.getCurToken().getKind()) {
4135 if (OOK
!= OO_None
) {
4136 SourceLocation OpLoc
= P
.ConsumeToken();
4137 SourceLocation SymbolLocations
[] = {OpLoc
, OpLoc
, SourceLocation()};
4138 ReductionId
.setOperatorFunctionId(OpLoc
, OOK
, SymbolLocations
);
4142 return P
.ParseUnqualifiedId(
4143 ReductionIdScopeSpec
, /*ObjectType=*/nullptr,
4144 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4145 /*AllowDestructorName*/ false,
4146 /*AllowConstructorName*/ false,
4147 /*AllowDeductionGuide*/ false, nullptr, ReductionId
);
4150 /// Checks if the token is a valid map-type-modifier.
4151 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4152 static OpenMPMapModifierKind
isMapModifier(Parser
&P
) {
4153 Token Tok
= P
.getCurToken();
4154 if (!Tok
.is(tok::identifier
))
4155 return OMPC_MAP_MODIFIER_unknown
;
4157 Preprocessor
&PP
= P
.getPreprocessor();
4158 OpenMPMapModifierKind TypeModifier
=
4159 static_cast<OpenMPMapModifierKind
>(getOpenMPSimpleClauseType(
4160 OMPC_map
, PP
.getSpelling(Tok
), P
.getLangOpts()));
4161 return TypeModifier
;
4164 /// Parse the mapper modifier in map, to, and from clauses.
4165 bool Parser::parseMapperModifier(Sema::OpenMPVarListDataTy
&Data
) {
4167 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::colon
);
4168 if (T
.expectAndConsume(diag::err_expected_lparen_after
, "mapper")) {
4169 SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4173 // Parse mapper-identifier
4174 if (getLangOpts().CPlusPlus
)
4175 ParseOptionalCXXScopeSpecifier(Data
.ReductionOrMapperIdScopeSpec
,
4176 /*ObjectType=*/nullptr,
4177 /*ObjectHasErrors=*/false,
4178 /*EnteringContext=*/false);
4179 if (Tok
.isNot(tok::identifier
) && Tok
.isNot(tok::kw_default
)) {
4180 Diag(Tok
.getLocation(), diag::err_omp_mapper_illegal_identifier
);
4181 SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4185 auto &DeclNames
= Actions
.getASTContext().DeclarationNames
;
4186 Data
.ReductionOrMapperId
= DeclarationNameInfo(
4187 DeclNames
.getIdentifier(Tok
.getIdentifierInfo()), Tok
.getLocation());
4190 return T
.consumeClose();
4193 /// Parse map-type-modifiers in map clause.
4194 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4195 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
4197 bool Parser::parseMapTypeModifiers(Sema::OpenMPVarListDataTy
&Data
) {
4198 while (getCurToken().isNot(tok::colon
)) {
4199 OpenMPMapModifierKind TypeModifier
= isMapModifier(*this);
4200 if (TypeModifier
== OMPC_MAP_MODIFIER_always
||
4201 TypeModifier
== OMPC_MAP_MODIFIER_close
||
4202 TypeModifier
== OMPC_MAP_MODIFIER_present
||
4203 TypeModifier
== OMPC_MAP_MODIFIER_ompx_hold
) {
4204 Data
.MapTypeModifiers
.push_back(TypeModifier
);
4205 Data
.MapTypeModifiersLoc
.push_back(Tok
.getLocation());
4206 if (PP
.LookAhead(0).isNot(tok::comma
) &&
4207 PP
.LookAhead(0).isNot(tok::colon
) && getLangOpts().OpenMP
>= 52)
4208 Diag(Tok
.getLocation(), diag::err_omp_missing_comma
)
4209 << "map type modifier";
4211 } else if (TypeModifier
== OMPC_MAP_MODIFIER_mapper
) {
4212 Data
.MapTypeModifiers
.push_back(TypeModifier
);
4213 Data
.MapTypeModifiersLoc
.push_back(Tok
.getLocation());
4215 if (parseMapperModifier(Data
))
4217 if (Tok
.isNot(tok::comma
) && Tok
.isNot(tok::colon
) &&
4218 getLangOpts().OpenMP
>= 52)
4219 Diag(Data
.MapTypeModifiersLoc
.back(), diag::err_omp_missing_comma
)
4220 << "map type modifier";
4223 // For the case of unknown map-type-modifier or a map-type.
4224 // Map-type is followed by a colon; the function returns when it
4225 // encounters a token followed by a colon.
4226 if (Tok
.is(tok::comma
)) {
4227 Diag(Tok
, diag::err_omp_map_type_modifier_missing
);
4231 // Potential map-type token as it is followed by a colon.
4232 if (PP
.LookAhead(0).is(tok::colon
))
4234 Diag(Tok
, diag::err_omp_unknown_map_type_modifier
)
4235 << (getLangOpts().OpenMP
>= 51 ? (getLangOpts().OpenMP
>= 52 ? 2 : 1)
4237 << getLangOpts().OpenMPExtensions
;
4240 if (getCurToken().is(tok::comma
))
4246 /// Checks if the token is a valid map-type.
4247 /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses.
4248 static OpenMPMapClauseKind
isMapType(Parser
&P
) {
4249 Token Tok
= P
.getCurToken();
4250 // The map-type token can be either an identifier or the C++ delete keyword.
4251 if (!Tok
.isOneOf(tok::identifier
, tok::kw_delete
))
4252 return OMPC_MAP_unknown
;
4253 Preprocessor
&PP
= P
.getPreprocessor();
4254 OpenMPMapClauseKind MapType
=
4255 static_cast<OpenMPMapClauseKind
>(getOpenMPSimpleClauseType(
4256 OMPC_map
, PP
.getSpelling(Tok
), P
.getLangOpts()));
4260 /// Parse map-type in map clause.
4261 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4262 /// where, map-type ::= to | from | tofrom | alloc | release | delete
4263 static void parseMapType(Parser
&P
, Sema::OpenMPVarListDataTy
&Data
) {
4264 Token Tok
= P
.getCurToken();
4265 if (Tok
.is(tok::colon
)) {
4266 P
.Diag(Tok
, diag::err_omp_map_type_missing
);
4269 Data
.ExtraModifier
= isMapType(P
);
4270 if (Data
.ExtraModifier
== OMPC_MAP_unknown
)
4271 P
.Diag(Tok
, diag::err_omp_unknown_map_type
);
4275 /// Parses simple expression in parens for single-expression clauses of OpenMP
4277 ExprResult
Parser::ParseOpenMPIteratorsExpr() {
4278 assert(Tok
.is(tok::identifier
) && PP
.getSpelling(Tok
) == "iterator" &&
4279 "Expected 'iterator' token.");
4280 SourceLocation IteratorKwLoc
= ConsumeToken();
4282 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
4283 if (T
.expectAndConsume(diag::err_expected_lparen_after
, "iterator"))
4286 SourceLocation LLoc
= T
.getOpenLocation();
4287 SmallVector
<Sema::OMPIteratorData
, 4> Data
;
4288 while (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::annot_pragma_openmp_end
)) {
4289 // Check if the type parsing is required.
4290 ParsedType IteratorType
;
4291 if (Tok
.isNot(tok::identifier
) || NextToken().isNot(tok::equal
)) {
4292 // identifier '=' is not found - parse type.
4293 TypeResult TR
= ParseTypeName();
4294 if (TR
.isInvalid()) {
4298 IteratorType
= TR
.get();
4301 // Parse identifier.
4302 IdentifierInfo
*II
= nullptr;
4303 SourceLocation IdLoc
;
4304 if (Tok
.is(tok::identifier
)) {
4305 II
= Tok
.getIdentifierInfo();
4306 IdLoc
= ConsumeToken();
4308 Diag(Tok
, diag::err_expected_unqualified_id
) << 0;
4312 SourceLocation AssignLoc
;
4313 if (Tok
.is(tok::equal
))
4314 AssignLoc
= ConsumeToken();
4316 Diag(Tok
, diag::err_omp_expected_equal_in_iterator
);
4318 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4319 ColonProtectionRAIIObject
ColonRAII(*this);
4321 SourceLocation Loc
= Tok
.getLocation();
4322 ExprResult LHS
= ParseCastExpression(AnyCastExpr
);
4323 ExprResult Begin
= Actions
.CorrectDelayedTyposInExpr(
4324 ParseRHSOfBinaryExpression(LHS
, prec::Conditional
));
4325 Begin
= Actions
.ActOnFinishFullExpr(Begin
.get(), Loc
,
4326 /*DiscardedValue=*/false);
4328 SourceLocation ColonLoc
;
4329 if (Tok
.is(tok::colon
))
4330 ColonLoc
= ConsumeToken();
4333 Loc
= Tok
.getLocation();
4334 LHS
= ParseCastExpression(AnyCastExpr
);
4335 ExprResult End
= Actions
.CorrectDelayedTyposInExpr(
4336 ParseRHSOfBinaryExpression(LHS
, prec::Conditional
));
4337 End
= Actions
.ActOnFinishFullExpr(End
.get(), Loc
,
4338 /*DiscardedValue=*/false);
4340 SourceLocation SecColonLoc
;
4342 // Parse optional step.
4343 if (Tok
.is(tok::colon
)) {
4345 SecColonLoc
= ConsumeToken();
4347 Loc
= Tok
.getLocation();
4348 LHS
= ParseCastExpression(AnyCastExpr
);
4349 Step
= Actions
.CorrectDelayedTyposInExpr(
4350 ParseRHSOfBinaryExpression(LHS
, prec::Conditional
));
4351 Step
= Actions
.ActOnFinishFullExpr(Step
.get(), Loc
,
4352 /*DiscardedValue=*/false);
4356 if (Tok
.isNot(tok::comma
) && Tok
.isNot(tok::r_paren
))
4357 Diag(Tok
, diag::err_omp_expected_punc_after_iterator
);
4358 if (Tok
.is(tok::comma
))
4361 Sema::OMPIteratorData
&D
= Data
.emplace_back();
4363 D
.DeclIdentLoc
= IdLoc
;
4364 D
.Type
= IteratorType
;
4365 D
.AssignLoc
= AssignLoc
;
4366 D
.ColonLoc
= ColonLoc
;
4367 D
.SecColonLoc
= SecColonLoc
;
4368 D
.Range
.Begin
= Begin
.get();
4369 D
.Range
.End
= End
.get();
4370 D
.Range
.Step
= Step
.get();
4374 SourceLocation RLoc
= Tok
.getLocation();
4375 if (!T
.consumeClose())
4376 RLoc
= T
.getCloseLocation();
4378 return Actions
.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc
, LLoc
, RLoc
,
4382 bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind
,
4383 Sema::OpenMPVarListDataTy
&Data
,
4384 const LangOptions
&LangOpts
) {
4385 // Currently the only reserved locator is 'omp_all_memory' which is only
4386 // allowed on a depend clause.
4387 if (Kind
!= OMPC_depend
|| LangOpts
.OpenMP
< 51)
4390 if (Tok
.is(tok::identifier
) &&
4391 Tok
.getIdentifierInfo()->isStr("omp_all_memory")) {
4393 if (Data
.ExtraModifier
== OMPC_DEPEND_outallmemory
||
4394 Data
.ExtraModifier
== OMPC_DEPEND_inoutallmemory
)
4395 Diag(Tok
, diag::warn_omp_more_one_omp_all_memory
);
4396 else if (Data
.ExtraModifier
!= OMPC_DEPEND_out
&&
4397 Data
.ExtraModifier
!= OMPC_DEPEND_inout
)
4398 Diag(Tok
, diag::err_omp_requires_out_inout_depend_type
);
4400 Data
.ExtraModifier
= Data
.ExtraModifier
== OMPC_DEPEND_out
4401 ? OMPC_DEPEND_outallmemory
4402 : OMPC_DEPEND_inoutallmemory
;
4409 /// Parse step size expression. Returns true if parsing is successfull,
4410 /// otherwise returns false.
4411 static bool parseStepSize(Parser
&P
, Sema::OpenMPVarListDataTy
&Data
,
4412 OpenMPClauseKind CKind
, SourceLocation ELoc
) {
4413 ExprResult Tail
= P
.ParseAssignmentExpression();
4414 Sema
&Actions
= P
.getActions();
4415 Tail
= Actions
.ActOnFinishFullExpr(Tail
.get(), ELoc
,
4416 /*DiscardedValue*/ false);
4417 if (Tail
.isUsable()) {
4418 Data
.DepModOrTailExpr
= Tail
.get();
4419 Token CurTok
= P
.getCurToken();
4420 if (CurTok
.isNot(tok::r_paren
) && CurTok
.isNot(tok::comma
)) {
4421 P
.Diag(CurTok
, diag::err_expected_punc
) << "step expression";
4428 /// Parses clauses with list.
4429 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind
,
4430 OpenMPClauseKind Kind
,
4431 SmallVectorImpl
<Expr
*> &Vars
,
4432 Sema::OpenMPVarListDataTy
&Data
) {
4433 UnqualifiedId UnqualifiedReductionId
;
4434 bool InvalidReductionId
= false;
4435 bool IsInvalidMapperModifier
= false;
4438 BalancedDelimiterTracker
T(*this, tok::l_paren
, tok::annot_pragma_openmp_end
);
4439 if (T
.expectAndConsume(diag::err_expected_lparen_after
,
4440 getOpenMPClauseName(Kind
).data()))
4443 bool HasIterator
= false;
4444 bool InvalidIterator
= false;
4445 bool NeedRParenForLinear
= false;
4446 BalancedDelimiterTracker
LinearT(*this, tok::l_paren
,
4447 tok::annot_pragma_openmp_end
);
4448 // Handle reduction-identifier for reduction clause.
4449 if (Kind
== OMPC_reduction
|| Kind
== OMPC_task_reduction
||
4450 Kind
== OMPC_in_reduction
) {
4451 Data
.ExtraModifier
= OMPC_REDUCTION_unknown
;
4452 if (Kind
== OMPC_reduction
&& getLangOpts().OpenMP
>= 50 &&
4453 (Tok
.is(tok::identifier
) || Tok
.is(tok::kw_default
)) &&
4454 NextToken().is(tok::comma
)) {
4455 // Parse optional reduction modifier.
4456 Data
.ExtraModifier
=
4457 getOpenMPSimpleClauseType(Kind
, PP
.getSpelling(Tok
), getLangOpts());
4458 Data
.ExtraModifierLoc
= Tok
.getLocation();
4460 assert(Tok
.is(tok::comma
) && "Expected comma.");
4461 (void)ConsumeToken();
4463 ColonProtectionRAIIObject
ColonRAII(*this);
4464 if (getLangOpts().CPlusPlus
)
4465 ParseOptionalCXXScopeSpecifier(Data
.ReductionOrMapperIdScopeSpec
,
4466 /*ObjectType=*/nullptr,
4467 /*ObjectHasErrors=*/false,
4468 /*EnteringContext=*/false);
4469 InvalidReductionId
= ParseReductionId(
4470 *this, Data
.ReductionOrMapperIdScopeSpec
, UnqualifiedReductionId
);
4471 if (InvalidReductionId
) {
4472 SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4475 if (Tok
.is(tok::colon
))
4476 Data
.ColonLoc
= ConsumeToken();
4478 Diag(Tok
, diag::warn_pragma_expected_colon
) << "reduction identifier";
4479 if (!InvalidReductionId
)
4480 Data
.ReductionOrMapperId
=
4481 Actions
.GetNameFromUnqualifiedId(UnqualifiedReductionId
);
4482 } else if (Kind
== OMPC_depend
|| Kind
== OMPC_doacross
) {
4483 if (getLangOpts().OpenMP
>= 50) {
4484 if (Tok
.is(tok::identifier
) && PP
.getSpelling(Tok
) == "iterator") {
4485 // Handle optional dependence modifier.
4486 // iterator(iterators-definition)
4487 // where iterators-definition is iterator-specifier [,
4488 // iterators-definition ]
4489 // where iterator-specifier is [ iterator-type ] identifier =
4490 // range-specification
4492 EnterScope(Scope::OpenMPDirectiveScope
| Scope::DeclScope
);
4493 ExprResult IteratorRes
= ParseOpenMPIteratorsExpr();
4494 Data
.DepModOrTailExpr
= IteratorRes
.get();
4496 ExpectAndConsume(tok::comma
);
4499 // Handle dependency type for depend clause.
4500 ColonProtectionRAIIObject
ColonRAII(*this);
4501 Data
.ExtraModifier
= getOpenMPSimpleClauseType(
4502 Kind
, Tok
.is(tok::identifier
) ? PP
.getSpelling(Tok
) : "",
4504 Data
.ExtraModifierLoc
= Tok
.getLocation();
4505 if ((Kind
== OMPC_depend
&& Data
.ExtraModifier
== OMPC_DEPEND_unknown
) ||
4506 (Kind
== OMPC_doacross
&&
4507 Data
.ExtraModifier
== OMPC_DOACROSS_unknown
)) {
4508 SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4512 // Special processing for depend(source) clause.
4513 if (DKind
== OMPD_ordered
&& Kind
== OMPC_depend
&&
4514 Data
.ExtraModifier
== OMPC_DEPEND_source
) {
4520 if (Tok
.is(tok::colon
)) {
4521 Data
.ColonLoc
= ConsumeToken();
4522 } else if (Kind
!= OMPC_doacross
|| Tok
.isNot(tok::r_paren
)) {
4523 Diag(Tok
, DKind
== OMPD_ordered
? diag::warn_pragma_expected_colon_r_paren
4524 : diag::warn_pragma_expected_colon
)
4525 << (Kind
== OMPC_depend
? "dependency type" : "dependence-type");
4527 if (Kind
== OMPC_doacross
) {
4528 if (Tok
.is(tok::identifier
) &&
4529 Tok
.getIdentifierInfo()->isStr("omp_cur_iteration")) {
4530 Data
.ExtraModifier
= Data
.ExtraModifier
== OMPC_DOACROSS_source
4531 ? OMPC_DOACROSS_source_omp_cur_iteration
4532 : OMPC_DOACROSS_sink_omp_cur_iteration
;
4535 if (Data
.ExtraModifier
== OMPC_DOACROSS_sink_omp_cur_iteration
) {
4536 if (Tok
.isNot(tok::minus
)) {
4537 Diag(Tok
, diag::err_omp_sink_and_source_iteration_not_allowd
)
4538 << getOpenMPClauseName(Kind
) << 0 << 0;
4539 SkipUntil(tok::r_paren
);
4543 SourceLocation Loc
= Tok
.getLocation();
4545 if (Tok
.isNot(tok::numeric_constant
) ||
4546 (PP
.parseSimpleIntegerLiteral(Tok
, Value
) && Value
!= 1)) {
4547 Diag(Loc
, diag::err_omp_sink_and_source_iteration_not_allowd
)
4548 << getOpenMPClauseName(Kind
) << 0 << 0;
4549 SkipUntil(tok::r_paren
);
4554 if (Data
.ExtraModifier
== OMPC_DOACROSS_source_omp_cur_iteration
) {
4555 if (Tok
.isNot(tok::r_paren
)) {
4556 Diag(Tok
, diag::err_omp_sink_and_source_iteration_not_allowd
)
4557 << getOpenMPClauseName(Kind
) << 1 << 1;
4558 SkipUntil(tok::r_paren
);
4562 // Only the 'sink' case has the expression list.
4563 if (Kind
== OMPC_doacross
&&
4564 (Data
.ExtraModifier
== OMPC_DOACROSS_source
||
4565 Data
.ExtraModifier
== OMPC_DOACROSS_source_omp_cur_iteration
||
4566 Data
.ExtraModifier
== OMPC_DOACROSS_sink_omp_cur_iteration
)) {
4572 } else if (Kind
== OMPC_linear
) {
4573 // Try to parse modifier if any.
4574 Data
.ExtraModifier
= OMPC_LINEAR_val
;
4575 if (Tok
.is(tok::identifier
) && PP
.LookAhead(0).is(tok::l_paren
)) {
4576 Data
.ExtraModifier
=
4577 getOpenMPSimpleClauseType(Kind
, PP
.getSpelling(Tok
), getLangOpts());
4578 Data
.ExtraModifierLoc
= ConsumeToken();
4579 LinearT
.consumeOpen();
4580 NeedRParenForLinear
= true;
4581 if (getLangOpts().OpenMP
>= 52)
4582 Diag(Data
.ExtraModifierLoc
, diag::err_omp_deprecate_old_syntax
)
4583 << "linear-modifier(list)" << getOpenMPClauseName(Kind
)
4584 << "linear(list: [linear-modifier,] step(step-size))";
4586 } else if (Kind
== OMPC_lastprivate
) {
4587 // Try to parse modifier if any.
4588 Data
.ExtraModifier
= OMPC_LASTPRIVATE_unknown
;
4589 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4590 // distribute and taskloop based directives.
4591 if ((getLangOpts().OpenMP
>= 50 && !isOpenMPDistributeDirective(DKind
) &&
4592 !isOpenMPTaskLoopDirective(DKind
)) &&
4593 Tok
.is(tok::identifier
) && PP
.LookAhead(0).is(tok::colon
)) {
4594 Data
.ExtraModifier
=
4595 getOpenMPSimpleClauseType(Kind
, PP
.getSpelling(Tok
), getLangOpts());
4596 Data
.ExtraModifierLoc
= Tok
.getLocation();
4598 assert(Tok
.is(tok::colon
) && "Expected colon.");
4599 Data
.ColonLoc
= ConsumeToken();
4601 } else if (Kind
== OMPC_map
) {
4602 // Handle optional iterator map modifier.
4603 if (Tok
.is(tok::identifier
) && PP
.getSpelling(Tok
) == "iterator") {
4605 EnterScope(Scope::OpenMPDirectiveScope
| Scope::DeclScope
);
4606 Data
.MapTypeModifiers
.push_back(OMPC_MAP_MODIFIER_iterator
);
4607 Data
.MapTypeModifiersLoc
.push_back(Tok
.getLocation());
4608 ExprResult IteratorRes
= ParseOpenMPIteratorsExpr();
4609 Data
.IteratorExpr
= IteratorRes
.get();
4611 ExpectAndConsume(tok::comma
);
4612 if (getLangOpts().OpenMP
< 52) {
4613 Diag(Tok
, diag::err_omp_unknown_map_type_modifier
)
4614 << (getLangOpts().OpenMP
>= 51 ? 1 : 0)
4615 << getLangOpts().OpenMPExtensions
;
4616 InvalidIterator
= true;
4619 // Handle map type for map clause.
4620 ColonProtectionRAIIObject
ColonRAII(*this);
4622 // The first identifier may be a list item, a map-type or a
4623 // map-type-modifier. The map-type can also be delete which has the same
4624 // spelling of the C++ delete keyword.
4625 Data
.ExtraModifier
= OMPC_MAP_unknown
;
4626 Data
.ExtraModifierLoc
= Tok
.getLocation();
4628 // Check for presence of a colon in the map clause.
4629 TentativeParsingAction
TPA(*this);
4630 bool ColonPresent
= false;
4631 if (SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4633 if (Tok
.is(tok::colon
))
4634 ColonPresent
= true;
4637 // Only parse map-type-modifier[s] and map-type if a colon is present in
4640 IsInvalidMapperModifier
= parseMapTypeModifiers(Data
);
4641 if (!IsInvalidMapperModifier
)
4642 parseMapType(*this, Data
);
4644 SkipUntil(tok::colon
, tok::annot_pragma_openmp_end
, StopBeforeMatch
);
4646 if (Data
.ExtraModifier
== OMPC_MAP_unknown
) {
4647 Data
.ExtraModifier
= OMPC_MAP_tofrom
;
4648 if (getLangOpts().OpenMP
>= 52) {
4649 if (DKind
== OMPD_target_enter_data
)
4650 Data
.ExtraModifier
= OMPC_MAP_to
;
4651 else if (DKind
== OMPD_target_exit_data
)
4652 Data
.ExtraModifier
= OMPC_MAP_from
;
4654 Data
.IsMapTypeImplicit
= true;
4657 if (Tok
.is(tok::colon
))
4658 Data
.ColonLoc
= ConsumeToken();
4659 } else if (Kind
== OMPC_to
|| Kind
== OMPC_from
) {
4660 while (Tok
.is(tok::identifier
)) {
4661 auto Modifier
= static_cast<OpenMPMotionModifierKind
>(
4662 getOpenMPSimpleClauseType(Kind
, PP
.getSpelling(Tok
), getLangOpts()));
4663 if (Modifier
== OMPC_MOTION_MODIFIER_unknown
)
4665 Data
.MotionModifiers
.push_back(Modifier
);
4666 Data
.MotionModifiersLoc
.push_back(Tok
.getLocation());
4668 if (Modifier
== OMPC_MOTION_MODIFIER_mapper
) {
4669 IsInvalidMapperModifier
= parseMapperModifier(Data
);
4670 if (IsInvalidMapperModifier
)
4673 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
4674 if (getLangOpts().OpenMP
< 51)
4676 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
4677 // TODO: Is that intentional?
4678 if (Tok
.is(tok::comma
))
4681 if (!Data
.MotionModifiers
.empty() && Tok
.isNot(tok::colon
)) {
4682 if (!IsInvalidMapperModifier
) {
4683 if (getLangOpts().OpenMP
< 51)
4684 Diag(Tok
, diag::warn_pragma_expected_colon
) << ")";
4686 Diag(Tok
, diag::warn_pragma_expected_colon
) << "motion modifier";
4688 SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4691 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
4692 // that intentional?
4693 if ((!Data
.MotionModifiers
.empty() || getLangOpts().OpenMP
>= 51) &&
4695 Data
.ColonLoc
= ConsumeToken();
4696 } else if (Kind
== OMPC_allocate
||
4697 (Kind
== OMPC_affinity
&& Tok
.is(tok::identifier
) &&
4698 PP
.getSpelling(Tok
) == "iterator")) {
4699 // Handle optional allocator expression followed by colon delimiter.
4700 ColonProtectionRAIIObject
ColonRAII(*this);
4701 TentativeParsingAction
TPA(*this);
4702 // OpenMP 5.0, 2.10.1, task Construct.
4703 // where aff-modifier is one of the following:
4704 // iterator(iterators-definition)
4706 if (Kind
== OMPC_allocate
) {
4707 Tail
= ParseAssignmentExpression();
4710 EnterScope(Scope::OpenMPDirectiveScope
| Scope::DeclScope
);
4711 Tail
= ParseOpenMPIteratorsExpr();
4713 Tail
= Actions
.CorrectDelayedTyposInExpr(Tail
);
4714 Tail
= Actions
.ActOnFinishFullExpr(Tail
.get(), T
.getOpenLocation(),
4715 /*DiscardedValue=*/false);
4716 if (Tail
.isUsable()) {
4717 if (Tok
.is(tok::colon
)) {
4718 Data
.DepModOrTailExpr
= Tail
.get();
4719 Data
.ColonLoc
= ConsumeToken();
4722 // Colon not found, parse only list of variables.
4726 // Parsing was unsuccessfull, revert and skip to the end of clause or
4729 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4732 } else if (Kind
== OMPC_adjust_args
) {
4733 // Handle adjust-op for adjust_args clause.
4734 ColonProtectionRAIIObject
ColonRAII(*this);
4735 Data
.ExtraModifier
= getOpenMPSimpleClauseType(
4736 Kind
, Tok
.is(tok::identifier
) ? PP
.getSpelling(Tok
) : "",
4738 Data
.ExtraModifierLoc
= Tok
.getLocation();
4739 if (Data
.ExtraModifier
== OMPC_ADJUST_ARGS_unknown
) {
4740 SkipUntil(tok::colon
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4744 if (Tok
.is(tok::colon
))
4745 Data
.ColonLoc
= Tok
.getLocation();
4746 ExpectAndConsume(tok::colon
, diag::warn_pragma_expected_colon
,
4752 (Kind
!= OMPC_reduction
&& Kind
!= OMPC_task_reduction
&&
4753 Kind
!= OMPC_in_reduction
&& Kind
!= OMPC_depend
&&
4754 Kind
!= OMPC_doacross
&& Kind
!= OMPC_map
) ||
4755 (Kind
== OMPC_reduction
&& !InvalidReductionId
) ||
4756 (Kind
== OMPC_map
&& Data
.ExtraModifier
!= OMPC_MAP_unknown
) ||
4757 (Kind
== OMPC_depend
&& Data
.ExtraModifier
!= OMPC_DEPEND_unknown
) ||
4758 (Kind
== OMPC_doacross
&& Data
.ExtraModifier
!= OMPC_DOACROSS_unknown
) ||
4759 (Kind
== OMPC_adjust_args
&&
4760 Data
.ExtraModifier
!= OMPC_ADJUST_ARGS_unknown
);
4761 const bool MayHaveTail
= (Kind
== OMPC_linear
|| Kind
== OMPC_aligned
);
4762 while (IsComma
|| (Tok
.isNot(tok::r_paren
) && Tok
.isNot(tok::colon
) &&
4763 Tok
.isNot(tok::annot_pragma_openmp_end
))) {
4764 ParseScope
OMPListScope(this, Scope::OpenMPDirectiveScope
);
4765 ColonProtectionRAIIObject
ColonRAII(*this, MayHaveTail
);
4766 if (!ParseOpenMPReservedLocator(Kind
, Data
, getLangOpts())) {
4768 ExprResult VarExpr
=
4769 Actions
.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
4770 if (VarExpr
.isUsable()) {
4771 Vars
.push_back(VarExpr
.get());
4773 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4778 IsComma
= Tok
.is(tok::comma
);
4781 else if (Tok
.isNot(tok::r_paren
) &&
4782 Tok
.isNot(tok::annot_pragma_openmp_end
) &&
4783 (!MayHaveTail
|| Tok
.isNot(tok::colon
)))
4784 Diag(Tok
, diag::err_omp_expected_punc
)
4785 << ((Kind
== OMPC_flush
) ? getOpenMPDirectiveName(OMPD_flush
)
4786 : getOpenMPClauseName(Kind
))
4787 << (Kind
== OMPC_flush
);
4790 // Parse ')' for linear clause with modifier.
4791 if (NeedRParenForLinear
)
4792 LinearT
.consumeClose();
4794 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
4795 // or parse ':' alignment.
4796 const bool MustHaveTail
= MayHaveTail
&& Tok
.is(tok::colon
);
4797 bool StepFound
= false;
4798 bool ModifierFound
= false;
4800 Data
.ColonLoc
= Tok
.getLocation();
4801 SourceLocation ELoc
= ConsumeToken();
4803 if (getLangOpts().OpenMP
>= 52 && Kind
== OMPC_linear
) {
4804 while (Tok
.isNot(tok::r_paren
)) {
4805 if (Tok
.is(tok::identifier
)) {
4806 // identifier could be a linear kind (val, uval, ref) or step
4807 // modifier or step size
4808 OpenMPLinearClauseKind LinKind
=
4809 static_cast<OpenMPLinearClauseKind
>(getOpenMPSimpleClauseType(
4810 Kind
, Tok
.isAnnotation() ? "" : PP
.getSpelling(Tok
),
4813 if (LinKind
== OMPC_LINEAR_step
) {
4815 Diag(Tok
, diag::err_omp_multiple_step_or_linear_modifier
) << 0;
4817 BalancedDelimiterTracker
StepT(*this, tok::l_paren
,
4818 tok::annot_pragma_openmp_end
);
4819 SourceLocation StepModifierLoc
= ConsumeToken();
4821 if (StepT
.consumeOpen())
4822 Diag(StepModifierLoc
, diag::err_expected_lparen_after
) << "step";
4824 // parse step size expression
4825 StepFound
= parseStepSize(*this, Data
, Kind
, Tok
.getLocation());
4827 Data
.StepModifierLoc
= StepModifierLoc
;
4830 StepT
.consumeClose();
4831 } else if (LinKind
>= 0 && LinKind
< OMPC_LINEAR_step
) {
4833 Diag(Tok
, diag::err_omp_multiple_step_or_linear_modifier
) << 1;
4835 Data
.ExtraModifier
= LinKind
;
4836 Data
.ExtraModifierLoc
= ConsumeToken();
4837 ModifierFound
= true;
4839 StepFound
= parseStepSize(*this, Data
, Kind
, Tok
.getLocation());
4842 // parse an integer expression as step size
4843 StepFound
= parseStepSize(*this, Data
, Kind
, Tok
.getLocation());
4846 if (Tok
.is(tok::comma
))
4848 if (Tok
.is(tok::r_paren
) || Tok
.is(tok::annot_pragma_openmp_end
))
4851 if (!StepFound
&& !ModifierFound
)
4852 Diag(ELoc
, diag::err_expected_expression
);
4854 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
4855 ExprResult Tail
= ParseAssignmentExpression();
4856 Tail
= Actions
.ActOnFinishFullExpr(Tail
.get(), ELoc
,
4857 /*DiscardedValue*/ false);
4858 if (Tail
.isUsable())
4859 Data
.DepModOrTailExpr
= Tail
.get();
4861 SkipUntil(tok::comma
, tok::r_paren
, tok::annot_pragma_openmp_end
,
4867 Data
.RLoc
= Tok
.getLocation();
4868 if (!T
.consumeClose())
4869 Data
.RLoc
= T
.getCloseLocation();
4870 // Exit from scope when the iterator is used in depend clause.
4873 return (Kind
!= OMPC_depend
&& Kind
!= OMPC_doacross
&& Kind
!= OMPC_map
&&
4875 (MustHaveTail
&& !Data
.DepModOrTailExpr
&& StepFound
) ||
4876 InvalidReductionId
|| IsInvalidMapperModifier
|| InvalidIterator
;
4879 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
4880 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
4881 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
4884 /// 'private' '(' list ')'
4885 /// firstprivate-clause:
4886 /// 'firstprivate' '(' list ')'
4887 /// lastprivate-clause:
4888 /// 'lastprivate' '(' list ')'
4890 /// 'shared' '(' list ')'
4892 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
4894 /// 'aligned' '(' list [ ':' alignment ] ')'
4895 /// reduction-clause:
4896 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
4897 /// task_reduction-clause:
4898 /// 'task_reduction' '(' reduction-identifier ':' list ')'
4899 /// in_reduction-clause:
4900 /// 'in_reduction' '(' reduction-identifier ':' list ')'
4901 /// copyprivate-clause:
4902 /// 'copyprivate' '(' list ')'
4904 /// 'flush' '(' list ')'
4906 /// 'depend' '(' in | out | inout : list | source ')'
4908 /// 'map' '(' [ [ always [,] ] [ close [,] ]
4909 /// [ mapper '(' mapper-identifier ')' [,] ]
4910 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
4912 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
4914 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
4915 /// use_device_ptr-clause:
4916 /// 'use_device_ptr' '(' list ')'
4917 /// use_device_addr-clause:
4918 /// 'use_device_addr' '(' list ')'
4919 /// is_device_ptr-clause:
4920 /// 'is_device_ptr' '(' list ')'
4921 /// has_device_addr-clause:
4922 /// 'has_device_addr' '(' list ')'
4923 /// allocate-clause:
4924 /// 'allocate' '(' [ allocator ':' ] list ')'
4925 /// nontemporal-clause:
4926 /// 'nontemporal' '(' list ')'
4927 /// inclusive-clause:
4928 /// 'inclusive' '(' list ')'
4929 /// exclusive-clause:
4930 /// 'exclusive' '(' list ')'
4932 /// For 'linear' clause linear-list may have the following forms:
4935 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
4936 OMPClause
*Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind
,
4937 OpenMPClauseKind Kind
,
4939 SourceLocation Loc
= Tok
.getLocation();
4940 SourceLocation LOpen
= ConsumeToken();
4941 SmallVector
<Expr
*, 4> Vars
;
4942 Sema::OpenMPVarListDataTy Data
;
4944 if (ParseOpenMPVarList(DKind
, Kind
, Vars
, Data
))
4949 OMPVarListLocTy
Locs(Loc
, LOpen
, Data
.RLoc
);
4950 return Actions
.ActOnOpenMPVarListClause(Kind
, Vars
, Locs
, Data
);