clang 24.0.0git
ParseOpenMP.cpp
Go to the documentation of this file.
1//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements parsing of all OpenMP directives and clauses.
10///
11//===----------------------------------------------------------------------===//
12
19#include "clang/Parse/Parser.h"
22#include "clang/Sema/Scope.h"
26#include "llvm/ADT/SmallBitVector.h"
27#include "llvm/ADT/StringSwitch.h"
28#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"
29#include "llvm/Frontend/OpenMP/OMPAssume.h"
30#include "llvm/Frontend/OpenMP/OMPContext.h"
31#include <climits>
32#include <optional>
33
34using namespace clang;
35using namespace llvm::omp;
36
37//===----------------------------------------------------------------------===//
38// OpenMP declarative directives.
39//===----------------------------------------------------------------------===//
40
41namespace {
42class DeclDirectiveListParserHelper final {
43 SmallVector<Expr *, 4> Identifiers;
44 Parser *P;
46
47public:
48 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
49 : P(P), Kind(Kind) {}
50 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
51 ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(
52 P->getCurScope(), SS, NameInfo, Kind);
53 if (Res.isUsable())
54 Identifiers.push_back(Res.get());
55 }
56 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
57};
58} // namespace
59
63 StringRef Name) {
64 unsigned Version = P.getLangOpts().OpenMP;
65 auto [D, VR] = getOpenMPDirectiveKindAndVersions(Name);
66 // "ORDERED" is parsed as OMPD_ordered_standalone.
67 if (D == Directive::OMPD_ordered_blockassoc)
68 D = Directive::OMPD_ordered_standalone;
69 assert(D == Kind && "Directive kind mismatch");
70 // Ignore the case Version > VR.Max: In OpenMP 6.0 all prior spellings
71 // are explicitly allowed.
72 if (static_cast<int>(Version) < VR.Min)
73 P.Diag(Loc, diag::warn_omp_future_directive_spelling) << Name;
74
75 return Kind;
76}
77
79 static const DirectiveNameParser DirParser;
80
81 const DirectiveNameParser::State *S = DirParser.initial();
82
83 Token Tok = P.getCurToken();
84 if (Tok.isAnnotation())
85 return OMPD_unknown;
86
87 std::string Concat = P.getPreprocessor().getSpelling(Tok);
88 SourceLocation Loc = Tok.getLocation();
89
90 S = DirParser.consume(S, Concat);
91 if (S == nullptr)
92 return OMPD_unknown;
93
94 while (!Tok.isAnnotation()) {
95 OpenMPDirectiveKind DKind = S->Value;
97 if (!Tok.isAnnotation()) {
98 std::string TS = P.getPreprocessor().getSpelling(Tok);
99 S = DirParser.consume(S, TS);
100 if (S == nullptr)
101 return checkOpenMPDirectiveName(P, Loc, DKind, Concat);
102 Concat += ' ' + TS;
103 P.ConsumeToken();
104 }
105 }
106
107 assert(S && "Should have exited early");
108 return checkOpenMPDirectiveName(P, Loc, S->Value, Concat);
109}
110
112 Token Tok = P.getCurToken();
113 Sema &Actions = P.getActions();
115 // Allow to use 'operator' keyword for C++ operators
116 bool WithOperator = false;
117 if (Tok.is(tok::kw_operator)) {
118 P.ConsumeToken();
119 Tok = P.getCurToken();
120 WithOperator = true;
121 }
122 switch (Tok.getKind()) {
123 case tok::plus: // '+'
124 OOK = OO_Plus;
125 break;
126 case tok::minus: // '-'
127 OOK = OO_Minus;
128 break;
129 case tok::star: // '*'
130 OOK = OO_Star;
131 break;
132 case tok::amp: // '&'
133 OOK = OO_Amp;
134 break;
135 case tok::pipe: // '|'
136 OOK = OO_Pipe;
137 break;
138 case tok::caret: // '^'
139 OOK = OO_Caret;
140 break;
141 case tok::ampamp: // '&&'
142 OOK = OO_AmpAmp;
143 break;
144 case tok::pipepipe: // '||'
145 OOK = OO_PipePipe;
146 break;
147 case tok::identifier: // identifier
148 if (!WithOperator)
149 break;
150 [[fallthrough]];
151 default:
152 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
153 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
155 return DeclarationName();
156 }
157 P.ConsumeToken();
158 auto &DeclNames = Actions.getASTContext().DeclarationNames;
159 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
160 : DeclNames.getCXXOperatorName(OOK);
161}
162
164Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
165 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
166 // Parse '('.
167 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
168 if (T.expectAndConsume(
169 diag::err_expected_lparen_after,
170 getOpenMPDirectiveName(OMPD_declare_reduction, OMPVersion).data())) {
171 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
172 return DeclGroupPtrTy();
173 }
174
175 DeclarationName Name = parseOpenMPReductionId(*this);
176 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
177 return DeclGroupPtrTy();
178
179 // Consume ':'.
180 bool IsCorrect = !ExpectAndConsume(tok::colon);
181
182 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
183 return DeclGroupPtrTy();
184
185 IsCorrect = IsCorrect && !Name.isEmpty();
186
187 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
188 Diag(Tok.getLocation(), diag::err_expected_type);
189 IsCorrect = false;
190 }
191
192 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
193 return DeclGroupPtrTy();
194
195 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
196 // Parse list of types until ':' token.
197 do {
198 ColonProtectionRAIIObject ColonRAII(*this);
199 SourceRange Range;
201 if (TR.isUsable()) {
202 QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(
203 Range.getBegin(), TR);
204 if (!ReductionType.isNull()) {
205 ReductionTypes.push_back(
206 std::make_pair(ReductionType, Range.getBegin()));
207 }
208 } else {
209 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
211 }
212
213 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
214 break;
215
216 // Consume ','.
217 if (ExpectAndConsume(tok::comma)) {
218 IsCorrect = false;
219 if (Tok.is(tok::annot_pragma_openmp_end)) {
220 Diag(Tok.getLocation(), diag::err_expected_type);
221 return DeclGroupPtrTy();
222 }
223 }
224 } while (Tok.isNot(tok::annot_pragma_openmp_end));
225
226 if (ReductionTypes.empty()) {
227 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
228 return DeclGroupPtrTy();
229 }
230
231 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
232 return DeclGroupPtrTy();
233
234 // Consume ':'.
235 if (ExpectAndConsume(tok::colon))
236 IsCorrect = false;
237
238 if (Tok.is(tok::annot_pragma_openmp_end)) {
239 Diag(Tok.getLocation(), diag::err_expected_expression);
240 return DeclGroupPtrTy();
241 }
242
243 DeclGroupPtrTy DRD =
244 Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveStart(
245 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,
246 AS);
247
248 // Parse <combiner> expression and then parse initializer if any for each
249 // correct type.
250 unsigned I = 0, E = ReductionTypes.size();
251 for (Decl *D : DRD.get()) {
252 TentativeParsingAction TPA(*this);
253 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
256 // Parse <combiner> expression.
257 Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
258 ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
259 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
260 Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerEnd(
261 D, CombinerResult.get());
262
263 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
264 Tok.isNot(tok::annot_pragma_openmp_end)) {
265 TPA.Commit();
266 IsCorrect = false;
267 break;
268 }
269 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
270 ExprResult InitializerResult;
271 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
272 // Parse <initializer> expression.
273 if (Tok.is(tok::identifier) &&
274 Tok.getIdentifierInfo()->isStr("initializer")) {
275 ConsumeToken();
276 } else {
277 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
278 TPA.Commit();
279 IsCorrect = false;
280 break;
281 }
282 // Parse '('.
283 BalancedDelimiterTracker T(*this, tok::l_paren,
284 tok::annot_pragma_openmp_end);
285 IsCorrect =
286 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
287 IsCorrect;
288 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
289 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
292 // Parse expression.
293 VarDecl *OmpPrivParm =
294 Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart(
295 getCurScope(), D);
296 // Check if initializer is omp_priv <init_expr> or something else.
297 if (Tok.is(tok::identifier) &&
298 Tok.getIdentifierInfo()->isStr("omp_priv")) {
299 ConsumeToken();
300 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
301 } else {
302 InitializerResult = Actions.ActOnFinishFullExpr(
303 ParseAssignmentExpression().get(), D->getLocation(),
304 /*DiscardedValue*/ false);
305 }
306 Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerEnd(
307 D, InitializerResult.get(), OmpPrivParm);
308 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
309 Tok.isNot(tok::annot_pragma_openmp_end)) {
310 TPA.Commit();
311 IsCorrect = false;
312 break;
313 }
314 IsCorrect =
315 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
316 }
317 }
318
319 ++I;
320 // Revert parsing if not the last type, otherwise accept it, we're done with
321 // parsing.
322 if (I != E)
323 TPA.Revert();
324 else
325 TPA.Commit();
326 }
327 return Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveEnd(
328 getCurScope(), DRD, IsCorrect);
329}
330
331void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
332 // Parse declarator '=' initializer.
333 // If a '==' or '+=' is found, suggest a fixit to '='.
334 if (isTokenEqualOrEqualTypo()) {
335 ConsumeToken();
336
337 if (Tok.is(tok::code_completion)) {
338 cutOffParsing();
339 Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),
340 OmpPrivParm);
341 Actions.FinalizeDeclaration(OmpPrivParm);
342 return;
343 }
344
345 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
346 ExprResult Init = ParseInitializer(OmpPrivParm);
347
348 if (Init.isInvalid()) {
349 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
350 Actions.ActOnInitializerError(OmpPrivParm);
351 } else {
352 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
353 /*DirectInit=*/false);
354 }
355 } else if (Tok.is(tok::l_paren)) {
356 // Parse C++ direct initializer: '(' expression-list ')'
357 BalancedDelimiterTracker T(*this, tok::l_paren);
358 T.consumeOpen();
359
360 ExprVector Exprs;
361
362 SourceLocation LParLoc = T.getOpenLocation();
363 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
364 QualType PreferredType =
365 Actions.CodeCompletion().ProduceConstructorSignatureHelp(
366 OmpPrivParm->getType()->getCanonicalTypeInternal(),
367 OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
368 CalledSignatureHelp = true;
369 return PreferredType;
370 };
371 if (ParseExpressionList(Exprs, [&] {
372 PreferredType.enterFunctionArgument(Tok.getLocation(),
373 RunSignatureHelp);
374 })) {
375 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
376 RunSignatureHelp();
377 Actions.ActOnInitializerError(OmpPrivParm);
378 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
379 } else {
380 // Match the ')'.
381 SourceLocation RLoc = Tok.getLocation();
382 if (!T.consumeClose())
383 RLoc = T.getCloseLocation();
384
386 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
387 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
388 /*DirectInit=*/true);
389 }
390 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
391 // Parse C++0x braced-init-list.
392 Diag(Tok, diag::compat_cxx11_generalized_initializer_lists);
393
394 ExprResult Init(ParseBraceInitializer());
395
396 if (Init.isInvalid()) {
397 Actions.ActOnInitializerError(OmpPrivParm);
398 } else {
399 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
400 /*DirectInit=*/true);
401 }
402 } else {
403 Actions.ActOnUninitializedDecl(OmpPrivParm);
404 }
405}
406
408Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
409 bool IsCorrect = true;
410 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
411 // Parse '('
412 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
413 if (T.expectAndConsume(
414 diag::err_expected_lparen_after,
415 getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion).data())) {
416 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
417 return DeclGroupPtrTy();
418 }
419
420 // Parse <mapper-identifier>
421 auto &DeclNames = Actions.getASTContext().DeclarationNames;
422 DeclarationName MapperId;
423 if (PP.LookAhead(0).is(tok::colon)) {
424 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
425 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
426 IsCorrect = false;
427 } else {
428 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
429 }
430 ConsumeToken();
431 // Consume ':'.
432 ExpectAndConsume(tok::colon);
433 } else {
434 // If no mapper identifier is provided, its name is "default" by default
435 MapperId =
436 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
437 }
438
439 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
440 return DeclGroupPtrTy();
441
442 // Parse <type> <var>
443 DeclarationName VName;
444 QualType MapperType;
445 SourceRange Range;
446 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
447 if (ParsedType.isUsable())
448 MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),
449 ParsedType);
450 if (MapperType.isNull())
451 IsCorrect = false;
452 if (!IsCorrect) {
453 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
454 return DeclGroupPtrTy();
455 }
456
457 // Consume ')'.
458 IsCorrect &= !T.consumeClose();
459 if (!IsCorrect) {
460 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
461 return DeclGroupPtrTy();
462 }
463
464 Scope *OuterScope = getCurScope();
465 // Enter scope.
466 DeclarationNameInfo DirName;
467 SourceLocation Loc = Tok.getLocation();
468 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
470 ParseScope OMPDirectiveScope(this, ScopeFlags);
471 Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,
472 getCurScope(), Loc);
473
474 // Add the mapper variable declaration.
475 ExprResult MapperVarRef =
476 Actions.OpenMP().ActOnOpenMPDeclareMapperDirectiveVarDecl(
477 getCurScope(), MapperType, Range.getBegin(), VName);
478
479 // Parse map clauses.
480 SmallVector<OMPClause *, 6> Clauses;
481 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
482 OpenMPClauseKind CKind = Tok.isAnnotation()
483 ? OMPC_unknown
484 : getOpenMPClauseKind(PP.getSpelling(Tok));
485 Actions.OpenMP().StartOpenMPClause(CKind);
486 OMPClause *Clause =
487 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
488 if (Clause)
489 Clauses.push_back(Clause);
490 else
491 IsCorrect = false;
492 // Skip ',' if any.
493 if (Tok.is(tok::comma))
494 ConsumeToken();
495 Actions.OpenMP().EndOpenMPClause();
496 }
497 if (Clauses.empty()) {
498 Diag(Tok, diag::err_omp_expected_clause)
499 << getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion);
500 IsCorrect = false;
501 }
502
503 // This needs to be called within the scope because
504 // processImplicitMapsWithDefaultMappers may add clauses when analyzing nested
505 // types. The scope used for calling ActOnOpenMPDeclareMapperDirective,
506 // however, needs to be the outer one, otherwise declared mappers don't become
507 // visible.
508 DeclGroupPtrTy DG = Actions.OpenMP().ActOnOpenMPDeclareMapperDirective(
509 OuterScope, Actions.getCurLexicalContext(), MapperId, MapperType,
510 Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
511 // Exit scope.
512 Actions.OpenMP().EndOpenMPDSABlock(nullptr);
513 OMPDirectiveScope.Exit();
514 if (!IsCorrect)
515 return DeclGroupPtrTy();
516
517 return DG;
518}
519
520TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
521 DeclarationName &Name,
522 AccessSpecifier AS) {
523 // Parse the common declaration-specifiers piece.
524 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
525 DeclSpec DS(AttrFactory);
526 ParseSpecifierQualifierList(DS, AS, DSC);
527
528 // Parse the declarator.
530 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
531 ParseDeclarator(DeclaratorInfo);
532 Range = DeclaratorInfo.getSourceRange();
533 if (DeclaratorInfo.getIdentifier() == nullptr) {
534 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
535 return true;
536 }
537 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
538
539 return Actions.OpenMP().ActOnOpenMPDeclareMapperVarDecl(getCurScope(),
540 DeclaratorInfo);
541}
542
543/// Parses 'omp begin declare variant' directive.
544// The syntax is:
545// { #pragma omp begin declare variant clause }
546// <function-declaration-or-definition-sequence>
547// { #pragma omp end declare variant }
548//
550 OMPTraitInfo *ParentTI =
551 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
552 ASTContext &ASTCtx = Actions.getASTContext();
553 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
554 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
555 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
556 ;
557 // Skip the last annot_pragma_openmp_end.
558 (void)ConsumeAnnotationToken();
559 return true;
560 }
561
562 // Skip last tokens.
563 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
564
565 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
566
567 VariantMatchInfo VMI;
568 TI.getAsVariantMatchInfo(ASTCtx, VMI);
569
570 std::function<void(StringRef)> DiagUnknownTrait = [this,
571 Loc](StringRef ISATrait) {
572 // TODO Track the selector locations in a way that is accessible here
573 // to improve the diagnostic location.
574 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
575 };
576 TargetOMPContext OMPCtx(
577 ASTCtx, std::move(DiagUnknownTrait),
578 /* CurrentFunctionDecl */ nullptr,
579 /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>(),
580 Actions.OpenMP().getOpenMPDeviceNum());
581
582 if (isVariantApplicableInContext(VMI, OMPCtx,
583 /*DeviceOrImplementationSetOnly=*/true)) {
584 Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
585 return false;
586 }
587
588 // Elide all the code till the matching end declare variant was found.
589 unsigned Nesting = 1;
590 SourceLocation DKLoc;
591 OpenMPDirectiveKind DK = OMPD_unknown;
592 do {
593 DKLoc = Tok.getLocation();
594 DK = parseOpenMPDirectiveKind(*this);
595 if (DK == OMPD_end_declare_variant)
596 --Nesting;
597 else if (DK == OMPD_begin_declare_variant)
598 ++Nesting;
599 if (!Nesting || isEofOrEom())
600 break;
602 } while (true);
603
604 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, DK,
605 Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
606 return false;
607}
608
609namespace {
610/// RAII that recreates function context for correct parsing of clauses of
611/// 'declare simd' construct.
612/// OpenMP, 2.8.2 declare simd Construct
613/// The expressions appearing in the clauses of this directive are evaluated in
614/// the scope of the arguments of the function declaration or definition.
615class FNContextRAII final {
616 Parser &P;
617 Sema::CXXThisScopeRAII *ThisScope;
619 bool HasFunScope = false;
620 FNContextRAII() = delete;
621 FNContextRAII(const FNContextRAII &) = delete;
622 FNContextRAII &operator=(const FNContextRAII &) = delete;
623
624public:
625 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
626 Decl *D = *Ptr.get().begin();
627 NamedDecl *ND = dyn_cast<NamedDecl>(D);
628 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
629 Sema &Actions = P.getActions();
630
631 // Allow 'this' within late-parsed attributes.
632 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
633 ND && ND->isCXXInstanceMember());
634
635 // If the Decl is templatized, add template parameters to scope.
636 // FIXME: Track CurTemplateDepth?
637 P.ReenterTemplateScopes(Scopes, D);
638
639 // If the Decl is on a function, add function parameters to the scope.
641 HasFunScope = true;
644 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
645 }
646 }
647 ~FNContextRAII() {
648 if (HasFunScope)
650 delete ThisScope;
651 }
652};
653} // namespace
654
655/// Parses clauses for 'declare simd' directive.
656/// clause:
657/// 'inbranch' | 'notinbranch'
658/// 'simdlen' '(' <expr> ')'
659/// { 'uniform' '(' <argument_list> ')' }
660/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
661/// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
663 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
667 SourceRange BSRange;
668 const Token &Tok = P.getCurToken();
669 bool IsError = false;
670 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
671 if (Tok.isNot(tok::identifier))
672 break;
673 OMPDeclareSimdDeclAttr::BranchStateTy Out;
674 IdentifierInfo *II = Tok.getIdentifierInfo();
675 StringRef ClauseName = II->getName();
676 // Parse 'inranch|notinbranch' clauses.
677 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
678 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
679 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
680 << ClauseName
681 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
682 IsError = true;
683 }
684 BS = Out;
685 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
686 P.ConsumeToken();
687 } else if (ClauseName == "simdlen") {
688 if (SimdLen.isUsable()) {
689 llvm::omp::Version OMPVersion =
691 P.Diag(Tok, diag::err_omp_more_one_clause)
692 << getOpenMPDirectiveName(OMPD_declare_simd, OMPVersion)
693 << ClauseName << 0;
694 IsError = true;
695 }
696 P.ConsumeToken();
697 SourceLocation RLoc;
698 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
699 if (SimdLen.isInvalid())
700 IsError = true;
701 } else {
702 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
703 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
704 CKind == OMPC_linear) {
706 SmallVectorImpl<Expr *> *Vars = &Uniforms;
707 if (CKind == OMPC_aligned) {
708 Vars = &Aligneds;
709 } else if (CKind == OMPC_linear) {
710 Data.ExtraModifier = OMPC_LINEAR_val;
711 Vars = &Linears;
712 }
713
714 P.ConsumeToken();
715 if (P.ParseOpenMPVarList(OMPD_declare_simd,
716 getOpenMPClauseKind(ClauseName), *Vars, Data))
717 IsError = true;
718 if (CKind == OMPC_aligned) {
719 Alignments.append(Aligneds.size() - Alignments.size(),
720 Data.DepModOrTailExpr);
721 } else if (CKind == OMPC_linear) {
722 assert(0 <= Data.ExtraModifier &&
723 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
724 "Unexpected linear modifier.");
726 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
727 Data.ExtraModifierLoc))
728 Data.ExtraModifier = OMPC_LINEAR_val;
729 LinModifiers.append(Linears.size() - LinModifiers.size(),
730 Data.ExtraModifier);
731 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
732 }
733 } else
734 // TODO: add parsing of other clauses.
735 break;
736 }
737 // Skip ',' if any.
738 if (Tok.is(tok::comma))
739 P.ConsumeToken();
740 }
741 return IsError;
742}
743
745Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
746 CachedTokens &Toks, SourceLocation Loc) {
747 PP.EnterToken(Tok, /*IsReinject*/ true);
748 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
749 /*IsReinject*/ true);
750 // Consume the previously pushed token.
751 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
752 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
753
754 FNContextRAII FnContext(*this, Ptr);
755 OMPDeclareSimdDeclAttr::BranchStateTy BS =
756 OMPDeclareSimdDeclAttr::BS_Undefined;
757 ExprResult Simdlen;
758 SmallVector<Expr *, 4> Uniforms;
759 SmallVector<Expr *, 4> Aligneds;
760 SmallVector<Expr *, 4> Alignments;
761 SmallVector<Expr *, 4> Linears;
762 SmallVector<unsigned, 4> LinModifiers;
763 SmallVector<Expr *, 4> Steps;
764 bool IsError =
765 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
766 Alignments, Linears, LinModifiers, Steps);
767 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
768 // Skip the last annot_pragma_openmp_end.
769 SourceLocation EndLoc = ConsumeAnnotationToken();
770 if (IsError)
771 return Ptr;
772 return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(
773 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
774 LinModifiers, Steps, SourceRange(Loc, EndLoc));
775}
776
777namespace {
778/// Constant used in the diagnostics to distinguish the levels in an OpenMP
779/// contexts: selector-set={selector(trait, ...), ...}, ....
780enum OMPContextLvl {
781 CONTEXT_SELECTOR_SET_LVL = 0,
782 CONTEXT_SELECTOR_LVL = 1,
783 CONTEXT_TRAIT_LVL = 2,
784};
785
786static StringRef stringLiteralParser(Parser &P) {
788 return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
789}
790
791static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
792 OMPContextLvl Lvl) {
793 if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
795 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
796 (void)P.ConsumeToken();
797 return Name;
798 }
799
801 return stringLiteralParser(P);
802
803 P.Diag(Tok.getLocation(),
804 diag::warn_omp_declare_variant_string_literal_or_identifier)
805 << Lvl;
806 return "";
807}
808
809static bool checkForDuplicates(Parser &P, StringRef Name,
810 SourceLocation NameLoc,
811 llvm::StringMap<SourceLocation> &Seen,
812 OMPContextLvl Lvl) {
813 auto Res = Seen.try_emplace(Name, NameLoc);
814 if (Res.second)
815 return false;
816
817 // Each trait-set-selector-name, trait-selector-name and trait-name can
818 // only be specified once.
819 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
820 << Lvl << Name;
821 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
822 << Lvl << Name;
823 return true;
824}
825} // namespace
826
827void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
828 llvm::omp::TraitSet Set,
829 llvm::omp::TraitSelector Selector,
830 llvm::StringMap<SourceLocation> &Seen) {
831 TIProperty.Kind = TraitProperty::invalid;
832
833 SourceLocation NameLoc = Tok.getLocation();
834 StringRef Name;
835 if (Selector == llvm::omp::TraitSelector::target_device_device_num) {
836 Name = "number";
837 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
838 ExprResult DeviceNumExprResult = ParseExpression();
839 if (DeviceNumExprResult.isUsable()) {
840 Expr *DeviceNumExpr = DeviceNumExprResult.get();
841 Actions.OpenMP().ActOnOpenMPDeviceNum(DeviceNumExpr);
842 }
843 return;
844 }
845 Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
846 if (Name.empty()) {
847 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
848 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
849 return;
850 }
851
852 TIProperty.RawString = Name;
853 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
854 if (TIProperty.Kind != TraitProperty::invalid) {
855 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
856 TIProperty.Kind = TraitProperty::invalid;
857 return;
858 }
859
860 // It follows diagnosis and helping notes.
861 // FIXME: We should move the diagnosis string generation into libFrontend.
862 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
863 << Name << getOpenMPContextTraitSelectorName(Selector)
864 << getOpenMPContextTraitSetName(Set);
865
866 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
867 if (SetForName != TraitSet::invalid) {
868 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
869 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
870 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
871 << Name << "<selector-name>"
872 << "(<property-name>)";
873 return;
874 }
875 TraitSelector SelectorForName =
876 getOpenMPContextTraitSelectorKind(Name, SetForName);
877 if (SelectorForName != TraitSelector::invalid) {
878 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
879 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
880 bool AllowsTraitScore = false;
881 bool RequiresProperty = false;
882 isValidTraitSelectorForTraitSet(
883 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
884 AllowsTraitScore, RequiresProperty);
885 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
886 << getOpenMPContextTraitSetName(
887 getOpenMPContextTraitSetForSelector(SelectorForName))
888 << Name << (RequiresProperty ? "(<property-name>)" : "");
889 return;
890 }
891 for (const auto &PotentialSet :
892 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
893 TraitSet::device, TraitSet::target_device}) {
894 TraitProperty PropertyForName =
895 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
896 if (PropertyForName == TraitProperty::invalid)
897 continue;
898 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
899 << getOpenMPContextTraitSetName(
900 getOpenMPContextTraitSetForProperty(PropertyForName))
901 << getOpenMPContextTraitSelectorName(
902 getOpenMPContextTraitSelectorForProperty(PropertyForName))
903 << ("(" + Name + ")").str();
904 return;
905 }
906 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
907 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
908}
909
911 OMPTraitProperty &TIProperty,
912 OMPTraitSelector &TISelector,
913 llvm::StringMap<SourceLocation> &Seen) {
914 assert(TISelector.Kind ==
915 llvm::omp::TraitSelector::implementation_extension &&
916 "Only for extension properties, e.g., "
917 "`implementation={extension(PROPERTY)}`");
918 if (TIProperty.Kind == TraitProperty::invalid)
919 return false;
920
921 if (TIProperty.Kind ==
922 TraitProperty::implementation_extension_disable_implicit_base)
923 return true;
924
925 if (TIProperty.Kind ==
926 TraitProperty::implementation_extension_allow_templates)
927 return true;
928
929 if (TIProperty.Kind ==
930 TraitProperty::implementation_extension_bind_to_declaration)
931 return true;
932
933 auto IsMatchExtension = [](OMPTraitProperty &TP) {
934 return (TP.Kind ==
935 llvm::omp::TraitProperty::implementation_extension_match_all ||
936 TP.Kind ==
937 llvm::omp::TraitProperty::implementation_extension_match_any ||
938 TP.Kind ==
939 llvm::omp::TraitProperty::implementation_extension_match_none);
940 };
941
942 if (IsMatchExtension(TIProperty)) {
943 for (OMPTraitProperty &SeenProp : TISelector.Properties)
944 if (IsMatchExtension(SeenProp)) {
945 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
946 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
947 SeenProp.Kind, SeenProp.RawString);
948 SourceLocation SeenLoc = Seen[SeenName];
949 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
950 << CONTEXT_TRAIT_LVL << SeenName;
951 return false;
952 }
953 return true;
954 }
955
956 llvm_unreachable("Unknown extension property!");
957}
958
959void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
960 llvm::omp::TraitSet Set,
961 llvm::StringMap<SourceLocation> &Seen) {
962 assert(TISelector.Kind != TraitSelector::user_condition &&
963 "User conditions are special properties not handled here!");
964
965 SourceLocation PropertyLoc = Tok.getLocation();
966 OMPTraitProperty TIProperty;
967 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
968
969 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
970 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
971 TISelector, Seen))
972 TIProperty.Kind = TraitProperty::invalid;
973
974 // If we have an invalid property here we already issued a warning.
975 if (TIProperty.Kind == TraitProperty::invalid) {
976 if (PropertyLoc != Tok.getLocation())
977 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
978 << CONTEXT_TRAIT_LVL;
979 return;
980 }
981
982 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
983 TISelector.Kind, Set)) {
984
985 // If we make it here the property, selector, set, score, condition, ... are
986 // all valid (or have been corrected). Thus we can record the property.
987 TISelector.Properties.push_back(TIProperty);
988 return;
989 }
990
991 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
992 << getOpenMPContextTraitPropertyName(TIProperty.Kind,
993 TIProperty.RawString)
994 << getOpenMPContextTraitSelectorName(TISelector.Kind)
995 << getOpenMPContextTraitSetName(Set);
996 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
997 << getOpenMPContextTraitPropertyName(TIProperty.Kind,
998 TIProperty.RawString)
999 << getOpenMPContextTraitSelectorName(
1000 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
1001 << getOpenMPContextTraitSetName(
1002 getOpenMPContextTraitSetForProperty(TIProperty.Kind));
1003 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1004 << CONTEXT_TRAIT_LVL;
1005}
1006
1007void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
1008 llvm::omp::TraitSet Set,
1009 llvm::StringMap<SourceLocation> &Seen) {
1010 TISelector.Kind = TraitSelector::invalid;
1011
1012 SourceLocation NameLoc = Tok.getLocation();
1013 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
1014 if (Name.empty()) {
1015 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1016 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1017 return;
1018 }
1019
1020 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name, Set);
1021 if (TISelector.Kind != TraitSelector::invalid) {
1022 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1023 TISelector.Kind = TraitSelector::invalid;
1024 return;
1025 }
1026
1027 // It follows diagnosis and helping notes.
1028 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1029 << Name << getOpenMPContextTraitSetName(Set);
1030
1031 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1032 if (SetForName != TraitSet::invalid) {
1033 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1034 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1035 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1036 << Name << "<selector-name>"
1037 << "<property-name>";
1038 return;
1039 }
1040 for (const auto &PotentialSet :
1041 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1042 TraitSet::device, TraitSet::target_device}) {
1043 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1044 PotentialSet, TraitSelector::invalid, Name);
1045 if (PropertyForName == TraitProperty::invalid)
1046 continue;
1047 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1048 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1049 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1050 << getOpenMPContextTraitSetName(
1051 getOpenMPContextTraitSetForProperty(PropertyForName))
1052 << getOpenMPContextTraitSelectorName(
1053 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1054 << ("(" + Name + ")").str();
1055 return;
1056 }
1057 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1058 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1059}
1060
1061/// Parse optional 'score' '(' <expr> ')' ':'.
1063 ExprResult ScoreExpr;
1064 llvm::SmallString<16> Buffer;
1065 StringRef SelectorName =
1066 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1067 if (SelectorName != "score")
1068 return ScoreExpr;
1069 (void)P.ConsumeToken();
1070 SourceLocation RLoc;
1071 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
1072 // Parse ':'
1073 if (P.getCurToken().is(tok::colon))
1074 (void)P.ConsumeAnyToken();
1075 else
1076 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
1077 << "':'"
1078 << "score expression";
1079 return ScoreExpr;
1080}
1081
1082void Parser::parseOMPContextSelector(
1083 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
1084 llvm::StringMap<SourceLocation> &SeenSelectors) {
1085 unsigned short OuterPC = ParenCount;
1086
1087 // If anything went wrong we issue an error or warning and then skip the rest
1088 // of the selector. However, commas are ambiguous so we look for the nesting
1089 // of parentheses here as well.
1090 auto FinishSelector = [OuterPC, this]() -> void {
1091 bool Done = false;
1092 while (!Done) {
1093 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1094 tok::annot_pragma_openmp_end},
1096 ;
1097 if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
1098 (void)ConsumeParen();
1099 if (OuterPC <= ParenCount) {
1100 Done = true;
1101 break;
1102 }
1103 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
1104 Done = true;
1105 break;
1106 }
1107 (void)ConsumeAnyToken();
1108 }
1109 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1110 << CONTEXT_SELECTOR_LVL;
1111 };
1112
1113 SourceLocation SelectorLoc = Tok.getLocation();
1114 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1115 if (TISelector.Kind == TraitSelector::invalid)
1116 return FinishSelector();
1117
1118 bool AllowsTraitScore = false;
1119 bool RequiresProperty = false;
1120 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
1121 RequiresProperty)) {
1122 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1123 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1124 << getOpenMPContextTraitSetName(Set);
1125 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1126 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1127 << getOpenMPContextTraitSetName(
1128 getOpenMPContextTraitSetForSelector(TISelector.Kind))
1129 << RequiresProperty;
1130 return FinishSelector();
1131 }
1132
1133 if (!RequiresProperty) {
1134 TISelector.Properties.push_back(
1135 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1136 getOpenMPContextTraitSelectorName(TISelector.Kind)});
1137 return;
1138 }
1139
1140 if (!Tok.is(tok::l_paren)) {
1141 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1142 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1143 << getOpenMPContextTraitSetName(Set);
1144 return FinishSelector();
1145 }
1146
1147 if (TISelector.Kind == TraitSelector::user_condition) {
1148 SourceLocation RLoc;
1149 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
1150 if (!Condition.isUsable())
1151 return FinishSelector();
1152 TISelector.ScoreOrCondition = Condition.get();
1153 TISelector.Properties.push_back(
1154 {TraitProperty::user_condition_unknown, "<condition>"});
1155 return;
1156 }
1157
1158 BalancedDelimiterTracker BDT(*this, tok::l_paren,
1159 tok::annot_pragma_openmp_end);
1160 // Parse '('.
1161 (void)BDT.consumeOpen();
1162
1163 SourceLocation ScoreLoc = Tok.getLocation();
1164 ExprResult Score = parseContextScore(*this);
1165
1166 if (!AllowsTraitScore && !Score.isUnset()) {
1167 if (Score.isUsable()) {
1168 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1169 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1170 << getOpenMPContextTraitSetName(Set) << Score.get();
1171 } else {
1172 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1173 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1174 << getOpenMPContextTraitSetName(Set) << "<invalid>";
1175 }
1176 Score = ExprResult();
1177 }
1178
1179 if (Score.isUsable())
1180 TISelector.ScoreOrCondition = Score.get();
1181
1182 llvm::StringMap<SourceLocation> SeenProperties;
1183 do {
1184 parseOMPContextProperty(TISelector, Set, SeenProperties);
1185 } while (TryConsumeToken(tok::comma));
1186
1187 // Parse ')'.
1188 BDT.consumeClose();
1189}
1190
1191void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
1192 llvm::StringMap<SourceLocation> &Seen) {
1193 TISet.Kind = TraitSet::invalid;
1194
1195 SourceLocation NameLoc = Tok.getLocation();
1196 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
1197 if (Name.empty()) {
1198 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1199 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1200 return;
1201 }
1202
1203 TISet.Kind = getOpenMPContextTraitSetKind(Name);
1204 if (TISet.Kind != TraitSet::invalid) {
1205 if (checkForDuplicates(*this, Name, NameLoc, Seen,
1206 CONTEXT_SELECTOR_SET_LVL))
1207 TISet.Kind = TraitSet::invalid;
1208 return;
1209 }
1210
1211 // It follows diagnosis and helping notes.
1212 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1213
1214 TraitSelector SelectorForName =
1215 getOpenMPContextTraitSelectorKind(Name, TISet.Kind);
1216 if (SelectorForName != TraitSelector::invalid) {
1217 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1218 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1219 bool AllowsTraitScore = false;
1220 bool RequiresProperty = false;
1221 isValidTraitSelectorForTraitSet(
1222 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1223 AllowsTraitScore, RequiresProperty);
1224 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1225 << getOpenMPContextTraitSetName(
1226 getOpenMPContextTraitSetForSelector(SelectorForName))
1227 << Name << (RequiresProperty ? "(<property-name>)" : "");
1228 return;
1229 }
1230 for (const auto &PotentialSet :
1231 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1232 TraitSet::device, TraitSet::target_device}) {
1233 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1234 PotentialSet, TraitSelector::invalid, Name);
1235 if (PropertyForName == TraitProperty::invalid)
1236 continue;
1237 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1238 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1239 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1240 << getOpenMPContextTraitSetName(
1241 getOpenMPContextTraitSetForProperty(PropertyForName))
1242 << getOpenMPContextTraitSelectorName(
1243 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1244 << ("(" + Name + ")").str();
1245 return;
1246 }
1247 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1248 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1249}
1250
1251void Parser::parseOMPContextSelectorSet(
1252 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1253 auto OuterBC = BraceCount;
1254
1255 // If anything went wrong we issue an error or warning and then skip the rest
1256 // of the set. However, commas are ambiguous so we look for the nesting
1257 // of braces here as well.
1258 auto FinishSelectorSet = [this, OuterBC]() -> void {
1259 bool Done = false;
1260 while (!Done) {
1261 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1262 tok::annot_pragma_openmp_end},
1264 ;
1265 if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
1266 (void)ConsumeBrace();
1267 if (OuterBC <= BraceCount) {
1268 Done = true;
1269 break;
1270 }
1271 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
1272 Done = true;
1273 break;
1274 }
1275 (void)ConsumeAnyToken();
1276 }
1277 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1278 << CONTEXT_SELECTOR_SET_LVL;
1279 };
1280
1281 parseOMPTraitSetKind(TISet, SeenSets);
1282 if (TISet.Kind == TraitSet::invalid)
1283 return FinishSelectorSet();
1284
1285 // Parse '='.
1286 if (!TryConsumeToken(tok::equal))
1287 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1288 << "="
1289 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
1290 "\"");
1291
1292 // Parse '{'.
1293 if (Tok.is(tok::l_brace)) {
1294 (void)ConsumeBrace();
1295 } else {
1296 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1297 << "{"
1298 << ("'=' that follows the context set name \"" +
1299 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1300 .str();
1301 }
1302
1303 llvm::StringMap<SourceLocation> SeenSelectors;
1304 do {
1305 OMPTraitSelector TISelector;
1306 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1307 if (TISelector.Kind != TraitSelector::invalid &&
1308 !TISelector.Properties.empty())
1309 TISet.Selectors.push_back(TISelector);
1310 } while (TryConsumeToken(tok::comma));
1311
1312 // Parse '}'.
1313 if (Tok.is(tok::r_brace)) {
1314 (void)ConsumeBrace();
1315 } else {
1316 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1317 << "}"
1318 << ("context selectors for the context set \"" +
1319 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1320 .str();
1321 }
1322}
1323
1324bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1325 llvm::StringMap<SourceLocation> SeenSets;
1326 do {
1327 OMPTraitSet TISet;
1328 parseOMPContextSelectorSet(TISet, SeenSets);
1329 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1330 TI.Sets.push_back(TISet);
1331 } while (TryConsumeToken(tok::comma));
1332
1333 return false;
1334}
1335
1336void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1337 CachedTokens &Toks,
1338 SourceLocation Loc) {
1339 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1340 PP.EnterToken(Tok, /*IsReinject*/ true);
1341 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1342 /*IsReinject*/ true);
1343 // Consume the previously pushed token.
1344 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1345 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1346
1347 FNContextRAII FnContext(*this, Ptr);
1348 // Parse function declaration id.
1349 SourceLocation RLoc;
1350 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1351 // instead of MemberExprs.
1352 ExprResult AssociatedFunction;
1353 {
1354 // Do not mark function as is used to prevent its emission if this is the
1355 // only place where it is used.
1356 EnterExpressionEvaluationContext Unevaluated(
1358 AssociatedFunction = ParseOpenMPParensExpr(
1359 getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion), RLoc,
1360 /*IsAddressOfOperand=*/true);
1361 }
1362 if (!AssociatedFunction.isUsable()) {
1363 if (!Tok.is(tok::annot_pragma_openmp_end))
1364 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1365 ;
1366 // Skip the last annot_pragma_openmp_end.
1367 (void)ConsumeAnnotationToken();
1368 return;
1369 }
1370
1371 OMPTraitInfo *ParentTI =
1372 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
1373 ASTContext &ASTCtx = Actions.getASTContext();
1374 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1375 SmallVector<Expr *, 6> AdjustNothing;
1376 SmallVector<Expr *, 6> AdjustNeedDevicePtr;
1377 SmallVector<Expr *, 6> AdjustNeedDeviceAddr;
1378 SmallVector<OMPInteropInfo, 3> AppendArgs;
1379 SourceLocation AdjustArgsLoc, AppendArgsLoc;
1380
1381 // At least one clause is required.
1382 if (Tok.is(tok::annot_pragma_openmp_end)) {
1383 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1384 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1385 }
1386
1387 bool IsError = false;
1388 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1389 OpenMPClauseKind CKind = Tok.isAnnotation()
1390 ? OMPC_unknown
1391 : getOpenMPClauseKind(PP.getSpelling(Tok));
1392 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind, OMPVersion)) {
1393 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1394 << (OMPVersion < 51 ? 0 : 1);
1395 IsError = true;
1396 }
1397 if (!IsError) {
1398 switch (CKind) {
1399 case OMPC_match:
1400 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
1401 break;
1402 case OMPC_adjust_args: {
1403 AdjustArgsLoc = Tok.getLocation();
1404 ConsumeToken();
1405 SemaOpenMP::OpenMPVarListDataTy Data;
1406 SmallVector<Expr *> Vars;
1407 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
1408 Vars, Data);
1409 if (!IsError) {
1410 switch (Data.ExtraModifier) {
1411 case OMPC_ADJUST_ARGS_nothing:
1412 llvm::append_range(AdjustNothing, Vars);
1413 break;
1414 case OMPC_ADJUST_ARGS_need_device_ptr:
1415 llvm::append_range(AdjustNeedDevicePtr, Vars);
1416 break;
1417 case OMPC_ADJUST_ARGS_need_device_addr:
1418 llvm::append_range(AdjustNeedDeviceAddr, Vars);
1419 break;
1420 default:
1421 llvm_unreachable("Unexpected 'adjust_args' clause modifier.");
1422 }
1423 }
1424 break;
1425 }
1426 case OMPC_append_args:
1427 if (!AppendArgs.empty()) {
1428 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1429 << getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion)
1430 << getOpenMPClauseName(CKind) << 0;
1431 IsError = true;
1432 }
1433 if (!IsError) {
1434 AppendArgsLoc = Tok.getLocation();
1435 ConsumeToken();
1436 IsError = parseOpenMPAppendArgs(AppendArgs);
1437 }
1438 break;
1439 default:
1440 llvm_unreachable("Unexpected clause for declare variant.");
1441 }
1442 }
1443 if (IsError) {
1444 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1445 ;
1446 // Skip the last annot_pragma_openmp_end.
1447 (void)ConsumeAnnotationToken();
1448 return;
1449 }
1450 // Skip ',' if any.
1451 if (Tok.is(tok::comma))
1452 ConsumeToken();
1453 }
1454
1455 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1456 Actions.OpenMP().checkOpenMPDeclareVariantFunction(
1457 Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
1458 SourceRange(Loc, Tok.getLocation()));
1459
1460 if (DeclVarData && !TI.Sets.empty())
1461 Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(
1462 DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1463 AdjustNeedDevicePtr, AdjustNeedDeviceAddr, AppendArgs, AdjustArgsLoc,
1464 AppendArgsLoc, SourceRange(Loc, Tok.getLocation()));
1465
1466 // Skip the last annot_pragma_openmp_end.
1467 (void)ConsumeAnnotationToken();
1468}
1469
1470bool Parser::parseOpenMPAppendArgs(
1471 SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
1472 bool HasError = false;
1473 // Parse '('.
1474 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1475 if (T.expectAndConsume(diag::err_expected_lparen_after,
1476 getOpenMPClauseName(OMPC_append_args).data()))
1477 return true;
1478
1479 // Parse the list of append-ops, each is;
1480 // interop(interop-type[,interop-type]...)
1481 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
1482 ConsumeToken();
1483 BalancedDelimiterTracker IT(*this, tok::l_paren,
1484 tok::annot_pragma_openmp_end);
1485 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
1486 return true;
1487
1488 OMPInteropInfo InteropInfo;
1489 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1490 HasError = true;
1491 else
1492 InteropInfos.push_back(InteropInfo);
1493
1494 IT.consumeClose();
1495 if (Tok.is(tok::comma))
1496 ConsumeToken();
1497 }
1498 if (!HasError && InteropInfos.empty()) {
1499 HasError = true;
1500 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
1501 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1503 }
1504 HasError = T.consumeClose() || HasError;
1505 return HasError;
1506}
1507
1508bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1509 OMPTraitInfo &TI,
1510 OMPTraitInfo *ParentTI) {
1511 // Parse 'match'.
1512 OpenMPClauseKind CKind = Tok.isAnnotation()
1513 ? OMPC_unknown
1514 : getOpenMPClauseKind(PP.getSpelling(Tok));
1515 if (CKind != OMPC_match) {
1516 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1517 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1518 return true;
1519 }
1520 (void)ConsumeToken();
1521 // Parse '('.
1522 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1523 if (T.expectAndConsume(diag::err_expected_lparen_after,
1524 getOpenMPClauseName(OMPC_match).data()))
1525 return true;
1526
1527 // Parse inner context selectors.
1528 parseOMPContextSelectors(Loc, TI);
1529
1530 // Parse ')'
1531 (void)T.consumeClose();
1532
1533 if (!ParentTI)
1534 return false;
1535
1536 // Merge the parent/outer trait info into the one we just parsed and diagnose
1537 // problems.
1538 // TODO: Keep some source location in the TI to provide better diagnostics.
1539 // TODO: Perform some kind of equivalence check on the condition and score
1540 // expressions.
1541 for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1542 bool MergedSet = false;
1543 for (OMPTraitSet &Set : TI.Sets) {
1544 if (Set.Kind != ParentSet.Kind)
1545 continue;
1546 MergedSet = true;
1547 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1548 bool MergedSelector = false;
1549 for (OMPTraitSelector &Selector : Set.Selectors) {
1550 if (Selector.Kind != ParentSelector.Kind)
1551 continue;
1552 MergedSelector = true;
1553 for (const OMPTraitProperty &ParentProperty :
1554 ParentSelector.Properties) {
1555 bool MergedProperty = false;
1556 for (OMPTraitProperty &Property : Selector.Properties) {
1557 // Ignore "equivalent" properties.
1558 if (Property.Kind != ParentProperty.Kind)
1559 continue;
1560
1561 // If the kind is the same but the raw string not, we don't want
1562 // to skip out on the property.
1563 MergedProperty |= Property.RawString == ParentProperty.RawString;
1564
1565 if (Property.RawString == ParentProperty.RawString &&
1566 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1567 continue;
1568
1569 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1570 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1571 } else if (Selector.ScoreOrCondition !=
1572 ParentSelector.ScoreOrCondition) {
1573 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1574 << getOpenMPContextTraitPropertyName(
1575 ParentProperty.Kind, ParentProperty.RawString)
1576 << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1577 << getOpenMPContextTraitSetName(ParentSet.Kind);
1578 }
1579 }
1580 if (!MergedProperty)
1581 Selector.Properties.push_back(ParentProperty);
1582 }
1583 }
1584 if (!MergedSelector)
1585 Set.Selectors.push_back(ParentSelector);
1586 }
1587 }
1588 if (!MergedSet)
1589 TI.Sets.push_back(ParentSet);
1590 }
1591
1592 return false;
1593}
1594
1595void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
1597 SourceLocation Loc) {
1598 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
1599 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1600 OpenMPClauseKind CKind = Tok.isAnnotation()
1601 ? OMPC_unknown
1602 : getOpenMPClauseKind(PP.getSpelling(Tok));
1603 if (DKind == OMPD_depobj && CKind == OMPC_update)
1604 CKind = OMPC_update_depend_objects;
1605 Actions.OpenMP().StartOpenMPClause(CKind);
1606 OMPClause *Clause =
1607 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
1608 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1610 SeenClauses[unsigned(CKind)] = true;
1611 if (Clause != nullptr)
1612 Clauses.push_back(Clause);
1613 if (Tok.is(tok::annot_pragma_openmp_end)) {
1614 Actions.OpenMP().EndOpenMPClause();
1615 break;
1616 }
1617 // Skip ',' if any.
1618 if (Tok.is(tok::comma))
1619 ConsumeToken();
1620 Actions.OpenMP().EndOpenMPClause();
1621 }
1622}
1623
1624void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
1625 SourceLocation Loc) {
1626 SmallVector<std::string, 4> Assumptions;
1627 bool SkippedClauses = false;
1628
1629 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
1630 BalancedDelimiterTracker T(*this, tok::l_paren,
1631 tok::annot_pragma_openmp_end);
1632 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1633 return;
1634 T.skipToEnd();
1635 if (IssueNote && T.getCloseLocation().isValid())
1636 Diag(T.getCloseLocation(),
1637 diag::note_omp_assumption_clause_continue_here);
1638 };
1639
1640 /// Helper to determine which AssumptionClauseMapping (ACM) in the
1641 /// AssumptionClauseMappings table matches \p RawString. The return value is
1642 /// the index of the matching ACM into the table or -1 if there was no match.
1643 auto MatchACMClause = [&](StringRef RawString) {
1644 llvm::StringSwitch<int> SS(RawString);
1645 unsigned ACMIdx = 0;
1646 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1647 if (ACMI.StartsWith)
1648 SS.StartsWith(ACMI.Identifier, ACMIdx++);
1649 else
1650 SS.Case(ACMI.Identifier, ACMIdx++);
1651 }
1652 return SS.Default(-1);
1653 };
1654
1655 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1656 IdentifierInfo *II = nullptr;
1657 SourceLocation StartLoc = Tok.getLocation();
1658 int Idx = -1;
1659 if (Tok.isAnyIdentifier()) {
1660 II = Tok.getIdentifierInfo();
1661 Idx = MatchACMClause(II->getName());
1662 }
1664
1665 bool NextIsLPar = Tok.is(tok::l_paren);
1666 // Handle unknown clauses by skipping them.
1667 if (Idx == -1) {
1668 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1669 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1670 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion)
1671 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1672 if (NextIsLPar)
1673 SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
1674 SkippedClauses = true;
1675 continue;
1676 }
1677 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1678 if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1679 // TODO: We ignore absent, contains, and holds assumptions for now. We
1680 // also do not verify the content in the parenthesis at all.
1681 SkippedClauses = true;
1682 SkipBraces(II->getName(), /* IssueNote */ false);
1683 continue;
1684 }
1685
1686 if (NextIsLPar) {
1687 Diag(Tok.getLocation(),
1688 diag::warn_omp_unknown_assumption_clause_without_args)
1689 << II;
1690 SkipBraces(II->getName(), /* IssueNote */ true);
1691 }
1692
1693 assert(II && "Expected an identifier clause!");
1694 std::string Assumption = II->getName().str();
1695 if (ACMI.StartsWith)
1696 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
1697 else
1698 Assumption = "omp_" + Assumption;
1699 Assumptions.push_back(Assumption);
1700 }
1701
1702 Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
1703 SkippedClauses);
1704}
1705
1706void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
1707 if (Actions.OpenMP().isInOpenMPAssumeScope())
1708 Actions.OpenMP().ActOnOpenMPEndAssumesDirective();
1709 else
1710 Diag(Loc, diag::err_expected_begin_assumes);
1711}
1712
1713/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1714///
1715/// default-clause:
1716/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')
1717///
1718/// proc_bind-clause:
1719/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1720///
1721/// device_type-clause:
1722/// 'device_type' '(' 'host' | 'nohost' | 'any' )'
1723namespace {
1724struct SimpleClauseData {
1725 unsigned Type;
1726 SourceLocation Loc;
1727 SourceLocation LOpen;
1728 SourceLocation TypeLoc;
1729 SourceLocation RLoc;
1730 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1731 SourceLocation TypeLoc, SourceLocation RLoc)
1732 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1733};
1734} // anonymous namespace
1735
1736static std::optional<SimpleClauseData>
1738 const Token &Tok = P.getCurToken();
1739 SourceLocation Loc = Tok.getLocation();
1740 SourceLocation LOpen = P.ConsumeToken();
1741 // Parse '('.
1742 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1743 if (T.expectAndConsume(diag::err_expected_lparen_after,
1744 getOpenMPClauseName(Kind).data()))
1745 return std::nullopt;
1746
1748 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1749 P.getLangOpts());
1750 SourceLocation TypeLoc = Tok.getLocation();
1751 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1752 Tok.isNot(tok::annot_pragma_openmp_end))
1753 P.ConsumeAnyToken();
1754
1755 // Parse ')'.
1756 SourceLocation RLoc = Tok.getLocation();
1757 if (!T.consumeClose())
1758 RLoc = T.getCloseLocation();
1759
1760 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1761}
1762
1763void Parser::ParseOMPDeclareTargetClauses(
1765 SourceLocation DeviceTypeLoc;
1766 bool RequiresToLinkLocalOrIndirectClause = false;
1767 bool HasToLinkLocalOrIndirectClause = false;
1768 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1769 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1770 bool HasIdentifier = Tok.is(tok::identifier);
1771 if (HasIdentifier) {
1772 // If we see any clause we need a to, link, or local clause.
1773 RequiresToLinkLocalOrIndirectClause = true;
1774 IdentifierInfo *II = Tok.getIdentifierInfo();
1775 StringRef ClauseName = II->getName();
1776 bool IsDeviceTypeClause =
1777 getLangOpts().OpenMP >= 50 &&
1778 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1779
1780 bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1781 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1782
1783 if (DTCI.Indirect && IsIndirectClause) {
1784 llvm::omp::Version OMPVersion =
1785 Actions.getLangOpts().getOpenMPVersion();
1786 Diag(Tok, diag::err_omp_more_one_clause)
1787 << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)
1788 << getOpenMPClauseName(OMPC_indirect) << 0;
1789 break;
1790 }
1791 bool IsToEnterLinkOrLocalClause =
1792 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1793 assert((!IsDeviceTypeClause || !IsToEnterLinkOrLocalClause) &&
1794 "Cannot be both!");
1795
1796 // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1797 // `enter` clause.
1798 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1799 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1800 break;
1801 }
1802 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1803 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1804 break;
1805 }
1806
1807 // The 'local' clause is only available in OpenMP 6.0.
1808 if (getLangOpts().OpenMP < 60 && ClauseName == "local") {
1809 Diag(Tok, getLangOpts().OpenMP >= 52
1810 ? diag::err_omp_declare_target_unexpected_clause_52
1811 : diag::err_omp_declare_target_unexpected_clause)
1812 << ClauseName
1813 << (getLangOpts().OpenMP >= 51 ? 4
1814 : getLangOpts().OpenMP >= 50 ? 2
1815 : 1);
1816 break;
1817 }
1818
1819 if (!IsDeviceTypeClause && !IsIndirectClause &&
1820 DTCI.Kind == OMPD_begin_declare_target) {
1821 Diag(Tok, getLangOpts().OpenMP >= 52
1822 ? diag::err_omp_declare_target_unexpected_clause_52
1823 : diag::err_omp_declare_target_unexpected_clause)
1824 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
1825 break;
1826 }
1827
1828 if (!IsDeviceTypeClause && !IsToEnterLinkOrLocalClause &&
1829 !IsIndirectClause) {
1830 Diag(Tok, getLangOpts().OpenMP >= 52
1831 ? diag::err_omp_declare_target_unexpected_clause_52
1832 : diag::err_omp_declare_target_unexpected_clause)
1833 << ClauseName
1834 << (getLangOpts().OpenMP > 52 ? 5
1835 : getLangOpts().OpenMP >= 51 ? 4
1836 : getLangOpts().OpenMP >= 50 ? 2
1837 : 1);
1838 break;
1839 }
1840
1841 if (IsToEnterLinkOrLocalClause || IsIndirectClause)
1842 HasToLinkLocalOrIndirectClause = true;
1843
1844 if (IsIndirectClause) {
1845 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1846 break;
1847 continue;
1848 }
1849 // Parse 'device_type' clause and go to next clause if any.
1850 if (IsDeviceTypeClause) {
1851 std::optional<SimpleClauseData> DevTypeData =
1852 parseOpenMPSimpleClause(*this, OMPC_device_type);
1853 if (DevTypeData) {
1854 if (DeviceTypeLoc.isValid()) {
1855 // We already saw another device_type clause, diagnose it.
1856 Diag(DevTypeData->Loc,
1857 diag::warn_omp_more_one_device_type_clause);
1858 break;
1859 }
1860 switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1861 case OMPC_DEVICE_TYPE_any:
1862 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1863 break;
1864 case OMPC_DEVICE_TYPE_host:
1865 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1866 break;
1867 case OMPC_DEVICE_TYPE_nohost:
1868 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1869 break;
1871 llvm_unreachable("Unexpected device_type");
1872 }
1873 DeviceTypeLoc = DevTypeData->Loc;
1874 }
1875 continue;
1876 }
1877 ConsumeToken();
1878 }
1879
1880 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1881 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1882 DeclarationNameInfo NameInfo) {
1883 NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
1884 getCurScope(), SS, NameInfo);
1885 if (!ND)
1886 return;
1887 SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
1888 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1889 if (!FirstMapping)
1890 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1891 << NameInfo.getName();
1892 };
1893 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1894 /*AllowScopeSpecifier=*/true))
1895 break;
1896 }
1897
1898 if (Tok.is(tok::l_paren)) {
1899 Diag(Tok,
1900 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1901 break;
1902 }
1903 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1904 Diag(Tok,
1905 getLangOpts().OpenMP >= 52
1906 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1907 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1908 break;
1909 }
1910
1911 // Consume optional ','.
1912 if (Tok.is(tok::comma))
1913 ConsumeToken();
1914 }
1915
1916 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1917 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1918
1919 // declare target requires at least one clause.
1920 if (DTCI.Kind == OMPD_declare_target && RequiresToLinkLocalOrIndirectClause &&
1921 !HasToLinkLocalOrIndirectClause)
1922 Diag(DTCI.Loc, diag::err_omp_declare_target_missing_required_clause)
1923 << (getLangOpts().OpenMP >= 60 ? 3
1924 : getLangOpts().OpenMP == 52 ? 2
1925 : getLangOpts().OpenMP == 51 ? 1
1926 : 0);
1927
1928 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1929}
1930
1931void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1932 // The last seen token is annot_pragma_openmp_end - need to check for
1933 // extra tokens.
1934 if (Tok.is(tok::annot_pragma_openmp_end))
1935 return;
1936
1937 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1938 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1939 << getOpenMPDirectiveName(DKind, OMPVersion);
1940 while (Tok.isNot(tok::annot_pragma_openmp_end))
1942}
1943
1944void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1945 OpenMPDirectiveKind ExpectedKind,
1946 OpenMPDirectiveKind FoundKind,
1947 SourceLocation BeginLoc,
1948 SourceLocation FoundLoc,
1949 bool SkipUntilOpenMPEnd) {
1950 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1951
1952 if (FoundKind == ExpectedKind) {
1954 skipUntilPragmaOpenMPEnd(ExpectedKind);
1955 return;
1956 }
1957
1958 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1959 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1960 << DiagSelection;
1961 Diag(BeginLoc, diag::note_matching)
1962 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + "'")
1963 .str();
1964 if (SkipUntilOpenMPEnd)
1965 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1966}
1967
1968void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
1969 OpenMPDirectiveKind EndDKind,
1970 SourceLocation DKLoc) {
1971 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
1972 Tok.getLocation(),
1973 /* SkipUntilOpenMPEnd */ false);
1974 // Skip the last annot_pragma_openmp_end.
1975 if (Tok.is(tok::annot_pragma_openmp_end))
1976 ConsumeAnnotationToken();
1977}
1978
1979Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1980 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
1981 DeclSpec::TST TagType, Decl *Tag) {
1982 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
1983 "Not an OpenMP directive!");
1984 ParsingOpenMPDirectiveRAII DirScope(*this);
1985 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1986 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1987
1988 SourceLocation Loc;
1989 OpenMPDirectiveKind DKind;
1990 if (Delayed) {
1991 TentativeParsingAction TPA(*this);
1992 Loc = ConsumeAnnotationToken();
1993 DKind = parseOpenMPDirectiveKind(*this);
1994 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1995 // Need to delay parsing until completion of the parent class.
1996 TPA.Revert();
1997 CachedTokens Toks;
1998 unsigned Cnt = 1;
1999 Toks.push_back(Tok);
2000 while (Cnt && Tok.isNot(tok::eof)) {
2001 (void)ConsumeAnyToken();
2002 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2003 ++Cnt;
2004 else if (Tok.is(tok::annot_pragma_openmp_end))
2005 --Cnt;
2006 Toks.push_back(Tok);
2007 }
2008 // Skip last annot_pragma_openmp_end.
2009 if (Cnt == 0)
2010 (void)ConsumeAnyToken();
2011 auto *LP = new LateParsedPragma(this, AS);
2012 LP->takeToks(Toks);
2013 getCurrentClass().LateParsedDeclarations.push_back(LP);
2014 return nullptr;
2015 }
2016 TPA.Commit();
2017 } else {
2018 Loc = ConsumeAnnotationToken();
2019 DKind = parseOpenMPDirectiveKind(*this);
2020 }
2021
2022 switch (DKind) {
2023 case OMPD_threadprivate: {
2024 ConsumeToken();
2025 DeclDirectiveListParserHelper Helper(this, DKind);
2026 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2027 /*AllowScopeSpecifier=*/true)) {
2028 skipUntilPragmaOpenMPEnd(DKind);
2029 // Skip the last annot_pragma_openmp_end.
2030 ConsumeAnnotationToken();
2031 return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2032 Loc, Helper.getIdentifiers());
2033 }
2034 break;
2035 }
2036 case OMPD_groupprivate: {
2037 ConsumeToken();
2038 DeclDirectiveListParserHelper Helper(this, DKind);
2039 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2040 /*AllowScopeSpecifier=*/true)) {
2041 skipUntilPragmaOpenMPEnd(DKind);
2042 // Skip the last annot_pragma_openmp_end.
2043 ConsumeAnnotationToken();
2044 return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2045 Loc, Helper.getIdentifiers());
2046 }
2047 break;
2048 }
2049 case OMPD_allocate: {
2050 ConsumeToken();
2051 DeclDirectiveListParserHelper Helper(this, DKind);
2052 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2053 /*AllowScopeSpecifier=*/true)) {
2054 SmallVector<OMPClause *, 1> Clauses;
2055 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2056 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
2057 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2058 OpenMPClauseKind CKind =
2059 Tok.isAnnotation() ? OMPC_unknown
2060 : getOpenMPClauseKind(PP.getSpelling(Tok));
2061 Actions.OpenMP().StartOpenMPClause(CKind);
2062 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2063 !SeenClauses[unsigned(CKind)]);
2064 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2066 SeenClauses[unsigned(CKind)] = true;
2067 if (Clause != nullptr)
2068 Clauses.push_back(Clause);
2069 if (Tok.is(tok::annot_pragma_openmp_end)) {
2070 Actions.OpenMP().EndOpenMPClause();
2071 break;
2072 }
2073 // Skip ',' if any.
2074 if (Tok.is(tok::comma))
2075 ConsumeToken();
2076 Actions.OpenMP().EndOpenMPClause();
2077 }
2078 skipUntilPragmaOpenMPEnd(DKind);
2079 }
2080 // Skip the last annot_pragma_openmp_end.
2081 ConsumeAnnotationToken();
2082 return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2083 Loc, Helper.getIdentifiers(), Clauses);
2084 }
2085 break;
2086 }
2087 case OMPD_requires: {
2088 SourceLocation StartLoc = ConsumeToken();
2089 SmallVector<OMPClause *, 5> Clauses;
2090 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2091 if (Tok.is(tok::annot_pragma_openmp_end)) {
2092 Diag(Tok, diag::err_omp_expected_clause)
2093 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2094 break;
2095 }
2096 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2097 OpenMPClauseKind CKind = Tok.isAnnotation()
2098 ? OMPC_unknown
2099 : getOpenMPClauseKind(PP.getSpelling(Tok));
2100 Actions.OpenMP().StartOpenMPClause(CKind);
2101 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
2102 !SeenClauses[unsigned(CKind)]);
2103 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2105 SeenClauses[unsigned(CKind)] = true;
2106 if (Clause != nullptr)
2107 Clauses.push_back(Clause);
2108 if (Tok.is(tok::annot_pragma_openmp_end)) {
2109 Actions.OpenMP().EndOpenMPClause();
2110 break;
2111 }
2112 // Skip ',' if any.
2113 if (Tok.is(tok::comma))
2114 ConsumeToken();
2115 Actions.OpenMP().EndOpenMPClause();
2116 }
2117 // Consume final annot_pragma_openmp_end
2118 if (Clauses.empty()) {
2119 Diag(Tok, diag::err_omp_expected_clause)
2120 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2121 ConsumeAnnotationToken();
2122 return nullptr;
2123 }
2124 ConsumeAnnotationToken();
2125 return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
2126 }
2127 case OMPD_error: {
2128 SmallVector<OMPClause *, 1> Clauses;
2129 SourceLocation StartLoc = ConsumeToken();
2130 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2131 Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2132 SourceLocation(),
2133 /*InExContext = */ false);
2134 break;
2135 }
2136 case OMPD_assumes:
2137 case OMPD_begin_assumes:
2138 ParseOpenMPAssumesDirective(DKind, ConsumeToken());
2139 break;
2140 case OMPD_end_assumes:
2141 ParseOpenMPEndAssumesDirective(ConsumeToken());
2142 break;
2143 case OMPD_declare_reduction:
2144 ConsumeToken();
2145 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2146 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2147 // Skip the last annot_pragma_openmp_end.
2148 ConsumeAnnotationToken();
2149 return Res;
2150 }
2151 break;
2152 case OMPD_declare_mapper: {
2153 ConsumeToken();
2154 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2155 // Skip the last annot_pragma_openmp_end.
2156 ConsumeAnnotationToken();
2157 return Res;
2158 }
2159 break;
2160 }
2161 case OMPD_begin_declare_variant: {
2162 ConsumeToken();
2164 // Skip the last annot_pragma_openmp_end.
2165 if (!isEofOrEom())
2166 ConsumeAnnotationToken();
2167 }
2168 return nullptr;
2169 }
2170 case OMPD_end_declare_variant: {
2171 ConsumeToken();
2172 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2173 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2174 else
2175 Diag(Loc, diag::err_expected_begin_declare_variant);
2176 // Skip the last annot_pragma_openmp_end.
2177 ConsumeAnnotationToken();
2178 return nullptr;
2179 }
2180 case OMPD_declare_variant:
2181 case OMPD_declare_simd: {
2182 // The syntax is:
2183 // { #pragma omp declare {simd|variant} }
2184 // <function-declaration-or-definition>
2185 //
2186 CachedTokens Toks;
2187 Toks.push_back(Tok);
2188 ConsumeToken();
2189 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2190 Toks.push_back(Tok);
2192 }
2193 Toks.push_back(Tok);
2195
2197 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2198 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2199 TagType, Tag);
2200 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
2201 // Here we expect to see some function declaration.
2202 if (AS == AS_none) {
2203 assert(TagType == DeclSpec::TST_unspecified);
2204 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2205 MaybeParseCXX11Attributes(Attrs);
2206 ParsingDeclSpec PDS(*this);
2207 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2208 } else {
2209 Ptr =
2210 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
2211 }
2212 }
2213 if (!Ptr) {
2214 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2215 << (DKind == OMPD_declare_simd ? 0 : 1);
2216 return DeclGroupPtrTy();
2217 }
2218
2219 DeclGroupRef DG = Ptr.get();
2220 SourceManager &SM = PP.getSourceManager();
2221 if (llvm::none_of(DG, [&](const Decl *D) {
2222 return SM.isBeforeInTranslationUnit(Loc, D->getBeginLoc());
2223 })) {
2224 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2225 << (DKind == OMPD_declare_simd ? 0 : 1);
2226 return DeclGroupPtrTy();
2227 }
2228
2229 if (DKind == OMPD_declare_simd)
2230 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2231 assert(DKind == OMPD_declare_variant &&
2232 "Expected declare variant directive only");
2233 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2234 return Ptr;
2235 }
2236 case OMPD_begin_declare_target:
2237 case OMPD_declare_target: {
2238 SourceLocation DTLoc = ConsumeAnyToken();
2239 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2240 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2241 if (DKind == OMPD_declare_target && !HasClauses &&
2242 getLangOpts().OpenMP >= 52)
2243 Diag(DTLoc, diag::warn_omp_deprecated_declare_target_delimited_form);
2244 if (HasClauses)
2245 ParseOMPDeclareTargetClauses(DTCI);
2246 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2247 !HasClauses ||
2248 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2249
2250 // Skip the last annot_pragma_openmp_end.
2252
2253 if (HasImplicitMappings) {
2254 Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
2255 return nullptr;
2256 }
2257
2258 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2259 llvm::SmallVector<Decl *, 4> Decls;
2260 for (auto &It : DTCI.ExplicitlyMapped)
2261 Decls.push_back(It.first);
2262 return Actions.BuildDeclaratorGroup(Decls);
2263 }
2264 case OMPD_end_declare_target: {
2265 if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2266 Diag(Tok, diag::err_omp_unexpected_directive)
2267 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2268 break;
2269 }
2270 const SemaOpenMP::DeclareTargetContextInfo &DTCI =
2271 Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
2272 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2273 return nullptr;
2274 }
2275 case OMPD_assume: {
2276 Diag(Tok, diag::err_omp_unexpected_directive)
2277 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2278 break;
2279 }
2280 case OMPD_unknown:
2281 Diag(Tok, diag::err_omp_unknown_directive);
2282 break;
2283 default:
2284 switch (getDirectiveCategory(DKind)) {
2285 case Category::Executable:
2286 case Category::Meta:
2287 case Category::Subsidiary:
2288 case Category::Utility:
2289 Diag(Tok, diag::err_omp_unexpected_directive)
2290 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2291 break;
2292 case Category::Declarative:
2293 case Category::Informational:
2294 break;
2295 }
2296 }
2297 while (Tok.isNot(tok::annot_pragma_openmp_end))
2300 return nullptr;
2301}
2302
2303StmtResult Parser::ParseOpenMPExecutableDirective(
2304 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2305 bool ReadDirectiveWithinMetadirective) {
2306 assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2307 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
2308
2309 bool HasAssociatedStatement = true;
2310 Association Assoc = getDirectiveAssociation(DKind);
2311
2312 // OMPD_scan and OMPD_section are both "separating", but section is treated
2313 // as if it was associated with a statement, while scan is not.
2314 if (DKind != OMPD_ordered_standalone && DKind != OMPD_section &&
2315 (Assoc == Association::None || Assoc == Association::Separating)) {
2316 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2317 ParsedStmtContext()) {
2318 Diag(Tok, diag::err_omp_immediate_directive)
2319 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2320 if (DKind == OMPD_error) {
2321 SkipUntil(tok::annot_pragma_openmp_end);
2322 return StmtError();
2323 }
2324 }
2325 HasAssociatedStatement = false;
2326 }
2327
2328 SourceLocation EndLoc;
2329 SmallVector<OMPClause *, 5> Clauses;
2330 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2331 DeclarationNameInfo DirName;
2332 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2333 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2335
2336 // Special processing for flush and depobj clauses.
2337 Token ImplicitTok;
2338 bool ImplicitClauseAllowed = false;
2339 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2340 ImplicitTok = Tok;
2341 ImplicitClauseAllowed = true;
2342 }
2343 ConsumeToken();
2344 // Parse directive name of the 'critical' directive if any.
2345 if (DKind == OMPD_critical) {
2346 BalancedDelimiterTracker T(*this, tok::l_paren,
2347 tok::annot_pragma_openmp_end);
2348 if (!T.consumeOpen()) {
2349 if (Tok.isAnyIdentifier()) {
2350 DirName =
2351 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2353 } else {
2354 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2355 }
2356 T.consumeClose();
2357 }
2358 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2359 CancelRegion = parseOpenMPDirectiveKind(*this);
2360 if (Tok.isNot(tok::annot_pragma_openmp_end))
2362 }
2363
2364 if (isOpenMPLoopDirective(DKind))
2365 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2366 if (isOpenMPSimdDirective(DKind))
2367 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2368 ParseScope OMPDirectiveScope(this, ScopeFlags);
2369 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2370 Loc);
2371
2372 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2373 // If we are parsing for a directive within a metadirective, the directive
2374 // ends with a ')'.
2375 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2376 while (Tok.isNot(tok::annot_pragma_openmp_end))
2378 break;
2379 }
2380 bool HasImplicitClause = false;
2381 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2382 HasImplicitClause = true;
2383 // Push copy of the current token back to stream to properly parse
2384 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2385 PP.EnterToken(Tok, /*IsReinject*/ true);
2386 PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2388 }
2389 OpenMPClauseKind CKind = Tok.isAnnotation()
2390 ? OMPC_unknown
2391 : getOpenMPClauseKind(PP.getSpelling(Tok));
2392 if (DKind == OMPD_depobj && CKind == OMPC_update)
2393 CKind = OMPC_update_depend_objects;
2394
2395 if (HasImplicitClause) {
2396 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2397 if (DKind == OMPD_flush) {
2398 CKind = OMPC_flush;
2399 } else {
2400 assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2401 CKind = OMPC_depobj;
2402 }
2403 }
2404 // No more implicit clauses allowed.
2405 ImplicitClauseAllowed = false;
2406 Actions.OpenMP().StartOpenMPClause(CKind);
2407 HasImplicitClause = false;
2408 SourceLocation ClauseLoc = Tok.getLocation();
2409
2410 OMPClause *Clause =
2411 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2412 SeenClauses[unsigned(CKind)] = true;
2413 if (Clause)
2414 Clauses.push_back(Clause);
2415
2416 // Skip ',' if any.
2417 if (Tok.is(tok::comma))
2418 ConsumeToken();
2419 Actions.OpenMP().EndOpenMPClause();
2420
2421 // If ParseOpenMPClause returned without consuming any tokens, skip
2422 // to end to avoid an infinite loop.
2423 if (Tok.getLocation() == ClauseLoc) {
2424 skipUntilPragmaOpenMPEnd(DKind);
2425 break;
2426 }
2427 }
2428 // End location of the directive.
2429 EndLoc = Tok.getLocation();
2430 // Consume final annot_pragma_openmp_end.
2431 ConsumeAnnotationToken();
2432
2433 assert(DKind != OMPD_ordered_blockassoc &&
2434 "Wrong kind for ordered directive");
2435 if (DKind == OMPD_ordered_standalone) {
2436 // If the depend or doacross clause is specified, the ordered construct
2437 // is a stand-alone directive.
2438 for (auto CK : {OMPC_depend, OMPC_doacross}) {
2439 if (SeenClauses[unsigned(CK)]) {
2440 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2441 ParsedStmtContext()) {
2442 Diag(Loc, diag::err_omp_immediate_directive)
2443 << getOpenMPDirectiveName(DKind, OMPVersion) << 1
2444 << getOpenMPClauseName(CK);
2445 }
2446 HasAssociatedStatement = false;
2447 }
2448 }
2449
2450 if (HasAssociatedStatement)
2451 DKind = OMPD_ordered_blockassoc;
2452 }
2453
2454 if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
2455 !SeenClauses[unsigned(OMPC_sizes)]) {
2456 Diag(Loc, diag::err_omp_required_clause)
2457 << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";
2458 }
2459 if (DKind == OMPD_split && !SeenClauses[unsigned(OMPC_counts)]) {
2460 Diag(Loc, diag::err_omp_required_clause)
2461 << getOpenMPDirectiveName(DKind, OMPVersion) << "counts";
2462 }
2463
2464 StmtResult AssociatedStmt;
2465 if (HasAssociatedStatement) {
2466 // The body is a block scope like in Lambdas and Blocks.
2467 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2468 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2469 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2470 // should have at least one compound statement scope within it.
2471 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2472 {
2473 Sema::CompoundScopeRAII Scope(Actions);
2474 AssociatedStmt = ParseStatement();
2475
2476 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2477 getLangOpts().OpenMPIRBuilder)
2478 AssociatedStmt =
2479 Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2480 }
2481 AssociatedStmt =
2482 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2483 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2484 DKind == OMPD_target_exit_data) {
2485 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2486 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2487 Actions.ActOnCompoundStmt(Loc, Loc, {},
2488 /*isStmtExpr=*/false));
2489 AssociatedStmt =
2490 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2491 }
2492
2493 StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
2494 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2495
2496 // Exit scope.
2497 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2498 OMPDirectiveScope.Exit();
2499
2500 return Directive;
2501}
2502
2503StmtResult Parser::ParseOpenMPInformationalDirective(
2504 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2505 bool ReadDirectiveWithinMetadirective) {
2506 assert(isOpenMPInformationalDirective(DKind) &&
2507 "Unexpected directive category");
2508
2509 bool HasAssociatedStatement = true;
2510
2511 SmallVector<OMPClause *, 5> Clauses;
2512 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2513 DeclarationNameInfo DirName;
2514 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2516 ParseScope OMPDirectiveScope(this, ScopeFlags);
2517
2518 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2519 Loc);
2520
2521 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2522 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2523 while (Tok.isNot(tok::annot_pragma_openmp_end))
2525 break;
2526 }
2527
2528 OpenMPClauseKind CKind = Tok.isAnnotation()
2529 ? OMPC_unknown
2530 : getOpenMPClauseKind(PP.getSpelling(Tok));
2531 Actions.OpenMP().StartOpenMPClause(CKind);
2532 OMPClause *Clause =
2533 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2534 SeenClauses[unsigned(CKind)] = true;
2535 if (Clause)
2536 Clauses.push_back(Clause);
2537
2538 if (Tok.is(tok::comma))
2539 ConsumeToken();
2540 Actions.OpenMP().EndOpenMPClause();
2541 }
2542
2543 SourceLocation EndLoc = Tok.getLocation();
2544 ConsumeAnnotationToken();
2545
2546 StmtResult AssociatedStmt;
2547 if (HasAssociatedStatement) {
2548 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2549 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2550 {
2551 Sema::CompoundScopeRAII Scope(Actions);
2552 AssociatedStmt = ParseStatement();
2553 }
2554 AssociatedStmt =
2555 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2556 }
2557
2558 StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
2559 DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2560
2561 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2562 OMPDirectiveScope.Exit();
2563
2564 return Directive;
2565}
2566
2567StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2568 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2569 if (!ReadDirectiveWithinMetadirective)
2570 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2571 "Not an OpenMP directive!");
2572 ParsingOpenMPDirectiveRAII DirScope(*this);
2573 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2574 SourceLocation Loc = ReadDirectiveWithinMetadirective
2575 ? Tok.getLocation()
2576 : ConsumeAnnotationToken();
2577 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
2579 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2580 Diag(Tok, diag::err_omp_unknown_directive);
2581 return StmtError();
2582 }
2583
2585
2586 bool IsExecutable = [&]() {
2587 if (DKind == OMPD_error) // OMPD_error is handled as executable
2588 return true;
2589 auto Res = getDirectiveCategory(DKind);
2590 return Res == Category::Executable || Res == Category::Subsidiary;
2591 }();
2592
2593 if (IsExecutable) {
2594 Directive = ParseOpenMPExecutableDirective(
2595 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2596 assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2597 return Directive;
2598 }
2599
2600 switch (DKind) {
2601 case OMPD_nothing:
2602 ConsumeToken();
2603 // If we are parsing the directive within a metadirective, the directive
2604 // ends with a ')'.
2605 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
2606 while (Tok.isNot(tok::annot_pragma_openmp_end))
2608 else
2609 skipUntilPragmaOpenMPEnd(DKind);
2610 if (Tok.is(tok::annot_pragma_openmp_end))
2611 ConsumeAnnotationToken();
2612 // return an empty statement
2613 return StmtEmpty();
2614 case OMPD_metadirective: {
2615 ConsumeToken();
2616 SmallVector<VariantMatchInfo, 4> VMIs;
2617
2618 // First iteration of parsing all clauses of metadirective.
2619 // This iteration only parses and collects all context selector ignoring the
2620 // associated directives.
2621 TentativeParsingAction TPA(*this);
2622 ASTContext &ASTContext = Actions.getASTContext();
2623
2624 BalancedDelimiterTracker T(*this, tok::l_paren,
2625 tok::annot_pragma_openmp_end);
2626 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2627 OpenMPClauseKind CKind = Tok.isAnnotation()
2628 ? OMPC_unknown
2629 : getOpenMPClauseKind(PP.getSpelling(Tok));
2630 // Check if the clause is unrecognized.
2631 if (CKind == OMPC_unknown) {
2632 Diag(Tok, diag::err_omp_expected_clause) << "metadirective";
2633 TPA.Revert();
2634 SkipUntil(tok::annot_pragma_openmp_end);
2635 return Directive;
2636 }
2637 if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)
2638 Diag(Tok, diag::err_omp_unexpected_clause)
2639 << getOpenMPClauseName(CKind) << "metadirective";
2640 if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)
2641 Diag(Tok, diag::warn_omp_default_deprecated);
2642
2643 SourceLocation Loc = ConsumeToken();
2644
2645 // Parse '('.
2646 if (T.expectAndConsume(diag::err_expected_lparen_after,
2647 getOpenMPClauseName(CKind).data())) {
2648 TPA.Revert();
2649 SkipUntil(tok::annot_pragma_openmp_end);
2650 return Directive;
2651 }
2652
2653 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2654 if (CKind == OMPC_when) {
2655 // parse and get OMPTraitInfo to pass to the When clause
2656 parseOMPContextSelectors(Loc, TI);
2657 if (TI.Sets.size() == 0) {
2658 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2659 TPA.Commit();
2660 return Directive;
2661 }
2662
2663 // Parse ':'
2664 if (Tok.is(tok::colon))
2666 else {
2667 Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2668 TPA.Commit();
2669 return Directive;
2670 }
2671 }
2672
2673 // Skip Directive for now. We will parse directive in the second iteration
2674 int paren = 0;
2675 while (Tok.isNot(tok::r_paren) || paren != 0) {
2676 if (Tok.is(tok::l_paren))
2677 paren++;
2678 if (Tok.is(tok::r_paren))
2679 paren--;
2680 if (Tok.is(tok::annot_pragma_openmp_end)) {
2681 Diag(Tok, diag::err_omp_expected_punc)
2682 << getOpenMPClauseName(CKind) << 0;
2683 TPA.Commit();
2684 return Directive;
2685 }
2687 }
2688 // Parse ')'
2689 if (Tok.is(tok::r_paren))
2690 T.consumeClose();
2691
2692 VariantMatchInfo VMI;
2693 TI.getAsVariantMatchInfo(ASTContext, VMI);
2694
2695 VMIs.push_back(VMI);
2696 }
2697
2698 TPA.Revert();
2699 // End of the first iteration. Parser is reset to the start of metadirective
2700
2701 std::function<void(StringRef)> DiagUnknownTrait =
2702 [this, Loc](StringRef ISATrait) {
2703 // TODO Track the selector locations in a way that is accessible here
2704 // to improve the diagnostic location.
2705 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2706 };
2707 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2708 /* CurrentFunctionDecl */ nullptr,
2709 ArrayRef<llvm::omp::TraitProperty>(),
2710 Actions.OpenMP().getOpenMPDeviceNum());
2711
2712 // A single match is returned for OpenMP 5.0
2713 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2714
2715 int Idx = 0;
2716 // In OpenMP 5.0 metadirective is either replaced by another directive or
2717 // ignored.
2718 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2719 // found by getBestWhenMatchForContext.
2720 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2721 // OpenMP 5.0 implementation - Skip to the best index found.
2722 if (Idx++ != BestIdx) {
2723 ConsumeToken(); // Consume clause name
2724 T.consumeOpen(); // Consume '('
2725 int paren = 0;
2726 // Skip everything inside the clause
2727 while (Tok.isNot(tok::r_paren) || paren != 0) {
2728 if (Tok.is(tok::l_paren))
2729 paren++;
2730 if (Tok.is(tok::r_paren))
2731 paren--;
2733 }
2734 // Parse ')'
2735 if (Tok.is(tok::r_paren))
2736 T.consumeClose();
2737 continue;
2738 }
2739
2740 OpenMPClauseKind CKind = Tok.isAnnotation()
2741 ? OMPC_unknown
2742 : getOpenMPClauseKind(PP.getSpelling(Tok));
2743 SourceLocation Loc = ConsumeToken();
2744
2745 // Parse '('.
2746 T.consumeOpen();
2747
2748 // Skip ContextSelectors for when clause
2749 if (CKind == OMPC_when) {
2750 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2751 // parse and skip the ContextSelectors
2752 parseOMPContextSelectors(Loc, TI);
2753
2754 // Parse ':'
2756 }
2757
2758 // If no directive is passed, skip in OpenMP 5.0.
2759 // TODO: Generate nothing directive from OpenMP 5.1.
2760 if (Tok.is(tok::r_paren)) {
2761 SkipUntil(tok::annot_pragma_openmp_end);
2762 break;
2763 }
2764
2765 // Parse Directive
2766 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2767 StmtCtx,
2768 /*ReadDirectiveWithinMetadirective=*/true);
2769 break;
2770 }
2771 // If no match is found and no otherwise clause is present, skip
2772 // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
2773 // if one was specified without an associated directive variant.
2774 if (BestIdx == -1 && Idx > 0) {
2775 assert(Tok.is(tok::annot_pragma_openmp_end) &&
2776 "Expecting the end of the pragma here");
2777 ConsumeAnnotationToken();
2778 return StmtEmpty();
2779 }
2780 break;
2781 }
2782 case OMPD_threadprivate: {
2783 // FIXME: Should this be permitted in C++?
2784 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2785 ParsedStmtContext()) {
2786 Diag(Tok, diag::err_omp_immediate_directive)
2787 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2788 }
2789 ConsumeToken();
2790 DeclDirectiveListParserHelper Helper(this, DKind);
2791 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2792 /*AllowScopeSpecifier=*/false)) {
2793 skipUntilPragmaOpenMPEnd(DKind);
2794 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2795 Loc, Helper.getIdentifiers());
2796 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2797 }
2798 SkipUntil(tok::annot_pragma_openmp_end);
2799 break;
2800 }
2801 case OMPD_groupprivate: {
2802 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2803 ParsedStmtContext()) {
2804 Diag(Tok, diag::err_omp_immediate_directive)
2805 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2806 }
2807 ConsumeToken();
2808 DeclDirectiveListParserHelper Helper(this, DKind);
2809 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2810 /*AllowScopeSpecifier=*/false)) {
2811 skipUntilPragmaOpenMPEnd(DKind);
2812 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2813 Loc, Helper.getIdentifiers());
2814 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2815 }
2816 SkipUntil(tok::annot_pragma_openmp_end);
2817 break;
2818 }
2819 case OMPD_allocate: {
2820 // FIXME: Should this be permitted in C++?
2821 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2822 ParsedStmtContext()) {
2823 Diag(Tok, diag::err_omp_immediate_directive)
2824 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2825 }
2826 ConsumeToken();
2827 DeclDirectiveListParserHelper Helper(this, DKind);
2828 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2829 /*AllowScopeSpecifier=*/false)) {
2830 SmallVector<OMPClause *, 1> Clauses;
2831 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2832 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2833 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2834 OpenMPClauseKind CKind =
2835 Tok.isAnnotation() ? OMPC_unknown
2836 : getOpenMPClauseKind(PP.getSpelling(Tok));
2837 Actions.OpenMP().StartOpenMPClause(CKind);
2838 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2839 !SeenClauses[unsigned(CKind)]);
2840 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2842 SeenClauses[unsigned(CKind)] = true;
2843 if (Clause != nullptr)
2844 Clauses.push_back(Clause);
2845 if (Tok.is(tok::annot_pragma_openmp_end)) {
2846 Actions.OpenMP().EndOpenMPClause();
2847 break;
2848 }
2849 // Skip ',' if any.
2850 if (Tok.is(tok::comma))
2851 ConsumeToken();
2852 Actions.OpenMP().EndOpenMPClause();
2853 }
2854 skipUntilPragmaOpenMPEnd(DKind);
2855 }
2856 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
2857 Loc, Helper.getIdentifiers(), Clauses);
2858 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2859 }
2860 SkipUntil(tok::annot_pragma_openmp_end);
2861 break;
2862 }
2863 case OMPD_declare_reduction:
2864 ConsumeToken();
2865 if (DeclGroupPtrTy Res =
2866 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2867 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2869 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2870 } else {
2871 SkipUntil(tok::annot_pragma_openmp_end);
2872 }
2873 break;
2874 case OMPD_declare_mapper: {
2875 ConsumeToken();
2876 if (DeclGroupPtrTy Res =
2877 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2878 // Skip the last annot_pragma_openmp_end.
2879 ConsumeAnnotationToken();
2880 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2881 } else {
2882 SkipUntil(tok::annot_pragma_openmp_end);
2883 }
2884 break;
2885 }
2886 case OMPD_declare_target: {
2887 SourceLocation DTLoc = ConsumeAnyToken();
2888 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2889 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2890 if (HasClauses)
2891 ParseOMPDeclareTargetClauses(DTCI);
2892 bool HasImplicitMappings =
2893 !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2894
2895 if (HasImplicitMappings) {
2896 Diag(Tok, diag::err_omp_unexpected_directive)
2897 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2898 SkipUntil(tok::annot_pragma_openmp_end);
2899 break;
2900 }
2901
2902 // Skip the last annot_pragma_openmp_end.
2904
2905 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2906 break;
2907 }
2908 case OMPD_begin_declare_variant: {
2909 ConsumeToken();
2911 // Skip the last annot_pragma_openmp_end.
2912 if (!isEofOrEom())
2913 ConsumeAnnotationToken();
2914 }
2915 return Directive;
2916 }
2917 case OMPD_end_declare_variant: {
2918 ConsumeToken();
2919 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2920 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2921 else
2922 Diag(Loc, diag::err_expected_begin_declare_variant);
2923 ConsumeAnnotationToken();
2924 break;
2925 }
2926 case OMPD_declare_simd:
2927 case OMPD_begin_declare_target:
2928 case OMPD_end_declare_target:
2929 case OMPD_requires:
2930 case OMPD_declare_variant:
2931 Diag(Tok, diag::err_omp_unexpected_directive)
2932 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2933 SkipUntil(tok::annot_pragma_openmp_end);
2934 break;
2935 case OMPD_assume: {
2936 ConsumeToken();
2937 Directive = ParseOpenMPInformationalDirective(
2938 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2939 assert(!Directive.isUnset() &&
2940 "Informational directive remains unprocessed");
2941 return Directive;
2942 }
2943 case OMPD_unknown:
2944 default:
2945 Diag(Tok, diag::err_omp_unknown_directive);
2946 SkipUntil(tok::annot_pragma_openmp_end);
2947 break;
2948 }
2949 return Directive;
2950}
2951
2952bool Parser::ParseOpenMPSimpleVarList(
2954 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2955 &Callback,
2956 bool AllowScopeSpecifier) {
2957 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
2958 // Parse '('.
2959 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2960 if (T.expectAndConsume(diag::err_expected_lparen_after,
2961 getOpenMPDirectiveName(Kind, OMPVersion).data()))
2962 return true;
2963 bool IsCorrect = true;
2964 bool NoIdentIsFound = true;
2965
2966 // Read tokens while ')' or annot_pragma_openmp_end is not found.
2967 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2968 CXXScopeSpec SS;
2969 UnqualifiedId Name;
2970 // Read var name.
2971 Token PrevTok = Tok;
2972 NoIdentIsFound = false;
2973
2974 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2975 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2976 /*ObjectHasErrors=*/false, false)) {
2977 IsCorrect = false;
2978 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2980 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2981 /*ObjectHadErrors=*/false, false, false,
2982 false, false, nullptr, Name)) {
2983 IsCorrect = false;
2984 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2986 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2987 Tok.isNot(tok::annot_pragma_openmp_end)) {
2988 IsCorrect = false;
2989 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2991 Diag(PrevTok.getLocation(), diag::err_expected)
2992 << tok::identifier
2993 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2994 } else {
2995 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2996 }
2997 // Consume ','.
2998 if (Tok.is(tok::comma)) {
2999 ConsumeToken();
3000 }
3001 }
3002
3003 if (NoIdentIsFound) {
3004 Diag(Tok, diag::err_expected) << tok::identifier;
3005 IsCorrect = false;
3006 }
3007
3008 // Parse ')'.
3009 IsCorrect = !T.consumeClose() && IsCorrect;
3010
3011 return !IsCorrect;
3012}
3013
3014OMPClause *Parser::ParseOpenMPSizesClause() {
3015 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3016 SmallVector<Expr *, 4> ValExprs;
3017 if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
3018 ValExprs))
3019 return nullptr;
3020
3021 return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
3022 OpenLoc, CloseLoc);
3023}
3024
3025OMPClause *Parser::ParseOpenMPCountsClause() {
3026 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3027 SmallVector<Expr *, 4> ValExprs;
3028 std::optional<unsigned> FillIdx;
3029 unsigned FillCount = 0;
3030 SourceLocation FillLoc;
3031
3032 assert(getOpenMPClauseName(OMPC_counts) == PP.getSpelling(Tok) &&
3033 "Expected parsing to start at clause name");
3034 ClauseNameLoc = ConsumeToken();
3035
3036 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3037 if (T.consumeOpen()) {
3038 Diag(Tok, diag::err_expected) << tok::l_paren;
3039 return nullptr;
3040 }
3041
3042 do {
3043 if (Tok.is(tok::identifier) &&
3044 Tok.getIdentifierInfo()->getName() == "omp_fill") {
3045 if (FillCount == 0)
3046 FillIdx = ValExprs.size();
3047 ++FillCount;
3048 FillLoc = Tok.getLocation();
3049 ConsumeToken();
3050 ValExprs.push_back(nullptr);
3051 } else {
3053 if (!Val.isUsable()) {
3054 T.skipToEnd();
3055 return nullptr;
3056 }
3057 ValExprs.push_back(Val.get());
3058 }
3059 } while (TryConsumeToken(tok::comma));
3060
3061 if (T.consumeClose())
3062 return nullptr;
3063 OpenLoc = T.getOpenLocation();
3064 CloseLoc = T.getCloseLocation();
3065
3066 return Actions.OpenMP().ActOnOpenMPCountsClause(
3067 ValExprs, ClauseNameLoc, OpenLoc, CloseLoc, FillIdx, FillLoc, FillCount);
3068}
3069
3070OMPClause *Parser::ParseOpenMPLoopRangeClause() {
3071 SourceLocation ClauseNameLoc = ConsumeToken();
3072 SourceLocation FirstLoc, CountLoc;
3073
3074 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3075 if (T.consumeOpen()) {
3076 Diag(Tok, diag::err_expected) << tok::l_paren;
3077 return nullptr;
3078 }
3079
3080 FirstLoc = Tok.getLocation();
3082 if (!FirstVal.isUsable()) {
3083 T.skipToEnd();
3084 return nullptr;
3085 }
3086
3087 ExpectAndConsume(tok::comma);
3088
3089 CountLoc = Tok.getLocation();
3091 if (!CountVal.isUsable()) {
3092 T.skipToEnd();
3093 return nullptr;
3094 }
3095
3096 T.consumeClose();
3097
3098 return Actions.OpenMP().ActOnOpenMPLoopRangeClause(
3099 FirstVal.get(), CountVal.get(), ClauseNameLoc, T.getOpenLocation(),
3100 FirstLoc, CountLoc, T.getCloseLocation());
3101}
3102
3103OMPClause *Parser::ParseOpenMPPermutationClause() {
3104 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3105 SmallVector<Expr *> ArgExprs;
3106 if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,
3107 CloseLoc, ArgExprs,
3108 /*ReqIntConst=*/true))
3109 return nullptr;
3110
3111 return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,
3112 OpenLoc, CloseLoc);
3113}
3114
3115OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3116 SourceLocation Loc = Tok.getLocation();
3118
3119 // Parse '('.
3120 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3121 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
3122 return nullptr;
3123 SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
3124 do {
3125 // Parse 'traits(expr) : Allocator' for >=5.2
3126 if (getLangOpts().OpenMP >= 52 && Tok.is(tok::identifier) &&
3127 Tok.getIdentifierInfo()->getName() == "traits") {
3128
3129 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3130
3131 ConsumeToken();
3132
3133 // Parse '(' <expr> ')'
3134 BalancedDelimiterTracker TraitParens(*this, tok::l_paren,
3135 tok::annot_pragma_openmp_end);
3136 TraitParens.consumeOpen();
3137 ExprResult AllocatorTraits =
3138 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3139 TraitParens.consumeClose();
3140
3141 if (AllocatorTraits.isInvalid()) {
3142 SkipUntil(
3143 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3145 break;
3146 }
3147
3148 // Expect ':'
3149 if (Tok.isNot(tok::colon)) {
3150 Diag(Tok, diag::err_expected) << tok::colon;
3151 SkipUntil(
3152 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3154 continue;
3155 }
3156 ConsumeToken();
3157
3158 CXXScopeSpec SS;
3159 ExprResult AllocatorExpr =
3160 getLangOpts().CPlusPlus
3161 ? ParseCXXIdExpression()
3162 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false);
3163
3164 if (AllocatorExpr.isInvalid()) {
3165 SkipUntil(
3166 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3168 break;
3169 }
3170
3171 D.Allocator = AllocatorExpr.get();
3172 D.AllocatorTraits = AllocatorTraits.get();
3173 D.LParenLoc = TraitParens.getOpenLocation();
3174 D.RParenLoc = TraitParens.getCloseLocation();
3175
3176 // Separator handling(;)
3177 if (Tok.is(tok::comma)) {
3178 // In 5.2, comma is invalid
3179 Diag(Tok.getLocation(), diag::err_omp_allocator_comma_separator)
3180 << FixItHint::CreateReplacement(Tok.getLocation(), ";");
3182 } else if (Tok.is(tok::semi)) {
3183 ConsumeAnyToken(); // valid separator
3184 }
3185
3186 continue;
3187 }
3188
3189 // Parse 'Allocator(expr)' for <5.2
3190 CXXScopeSpec SS;
3191 ExprResult Allocator =
3192 getLangOpts().CPlusPlus
3193 ? ParseCXXIdExpression()
3194 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false);
3195 if (Allocator.isInvalid()) {
3196 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3197 StopBeforeMatch);
3198 break;
3199 }
3200 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3201 D.Allocator = Allocator.get();
3202 if (Tok.is(tok::l_paren)) {
3203 BalancedDelimiterTracker T(*this, tok::l_paren,
3204 tok::annot_pragma_openmp_end);
3205 T.consumeOpen();
3206 ExprResult AllocatorTraits =
3207 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3208 T.consumeClose();
3209 if (AllocatorTraits.isInvalid()) {
3210 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3211 StopBeforeMatch);
3212 break;
3213 }
3214 D.AllocatorTraits = AllocatorTraits.get();
3215 D.LParenLoc = T.getOpenLocation();
3216 D.RParenLoc = T.getCloseLocation();
3217
3218 // Deprecation diagnostic in >= 5.2
3219 if (getLangOpts().OpenMP >= 52) {
3220 Diag(Loc, diag::err_omp_deprecate_old_syntax)
3221 << "allocator(expr)" // %0: old form
3222 << "uses_allocators" // %1: clause name
3223 << "traits(expr): alloc"; // %2: suggested new form
3224 }
3225 }
3226 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3227 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
3228 // Parse ','
3229 if (Tok.is(tok::comma))
3230 ConsumeAnyToken();
3231 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
3232 T.consumeClose();
3233 return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3234 Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
3235}
3236
3237OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3238 OpenMPClauseKind CKind, bool FirstClause) {
3239 OMPClauseKind = CKind;
3240 OMPClause *Clause = nullptr;
3241 bool ErrorFound = false;
3242 bool WrongDirective = false;
3243 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
3244
3245 auto CheckClauseValid = [&](OpenMPDirectiveKind D, OpenMPClauseKind C) {
3246 if (!isAllowedClauseForDirective(D, C, OMPVersion)) {
3247 Diag(Tok, diag::err_omp_unexpected_clause)
3248 << getOpenMPClauseName(C) << getOpenMPDirectiveName(D, OMPVersion);
3249 ErrorFound = true;
3250 WrongDirective = true;
3251 }
3252 };
3253
3254 if (CKind != OMPC_unknown) {
3255 // Check if clause is allowed for the given directive.
3256 assert(DKind != OMPD_ordered_blockassoc &&
3257 "Wrong kind for ordered directive");
3258 if (DKind == OMPD_ordered_standalone) {
3259 // Initially OMPD_ordered_standalone is used for ORDERED, before the
3260 // actual kind can be determined.
3261 if (!isAllowedClauseForDirective(DKind, CKind, OMPVersion))
3262 CheckClauseValid(OMPD_ordered_blockassoc, CKind);
3263 } else {
3264 CheckClauseValid(DKind, CKind);
3265 }
3266 }
3267
3268 switch (CKind) {
3269 case OMPC_final:
3270 case OMPC_safelen:
3271 case OMPC_simdlen:
3272 case OMPC_collapse:
3273 case OMPC_ordered:
3274 case OMPC_priority:
3275 case OMPC_grainsize:
3276 case OMPC_num_tasks:
3277 case OMPC_hint:
3278 case OMPC_allocator:
3279 case OMPC_depobj:
3280 case OMPC_detach:
3281 case OMPC_novariants:
3282 case OMPC_nocontext:
3283 case OMPC_filter:
3284 case OMPC_partial:
3285 case OMPC_align:
3286 case OMPC_message:
3287 case OMPC_ompx_dyn_cgroup_mem:
3288 case OMPC_dyn_groupprivate:
3289 case OMPC_transparent:
3290 // OpenMP [2.5, Restrictions]
3291 // At most one num_threads clause can appear on the directive.
3292 // OpenMP [2.8.1, simd construct, Restrictions]
3293 // Only one safelen clause can appear on a simd directive.
3294 // Only one simdlen clause can appear on a simd directive.
3295 // Only one collapse clause can appear on a simd directive.
3296 // OpenMP [2.11.1, task Construct, Restrictions]
3297 // At most one if clause can appear on the directive.
3298 // At most one final clause can appear on the directive.
3299 // OpenMP [teams Construct, Restrictions]
3300 // At most one num_teams clause can appear on the directive.
3301 // At most one thread_limit clause can appear on the directive.
3302 // OpenMP [2.9.1, task Construct, Restrictions]
3303 // At most one priority clause can appear on the directive.
3304 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3305 // At most one grainsize clause can appear on the directive.
3306 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3307 // At most one num_tasks clause can appear on the directive.
3308 // OpenMP [2.11.3, allocate Directive, Restrictions]
3309 // At most one allocator clause can appear on the directive.
3310 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3311 // At most one detach clause can appear on the directive.
3312 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3313 // At most one novariants clause can appear on a dispatch directive.
3314 // At most one nocontext clause can appear on a dispatch directive.
3315 // OpenMP [5.1, error directive, Restrictions]
3316 // At most one message clause can appear on the directive
3317 if (!FirstClause) {
3318 Diag(Tok, diag::err_omp_more_one_clause)
3319 << getOpenMPDirectiveName(DKind, OMPVersion)
3320 << getOpenMPClauseName(CKind) << 0;
3321 ErrorFound = true;
3322 }
3323
3324 if (CKind == OMPC_transparent && PP.LookAhead(0).isNot(tok::l_paren)) {
3325 SourceLocation Loc = ConsumeToken();
3326 SourceLocation LLoc = Tok.getLocation();
3327 if (!WrongDirective)
3328 Clause = Actions.OpenMP().ActOnOpenMPTransparentClause(nullptr, LLoc,
3329 LLoc, Loc);
3330 break;
3331 }
3332 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3333 PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3334 Clause = ParseOpenMPClause(CKind, WrongDirective);
3335 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
3336 CKind == OMPC_dyn_groupprivate)
3337 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3338 else
3339 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3340 break;
3341 case OMPC_threadset:
3342 case OMPC_fail:
3343 case OMPC_proc_bind:
3344 case OMPC_atomic_default_mem_order:
3345 case OMPC_at:
3346 case OMPC_severity:
3347 case OMPC_bind:
3348 // OpenMP [2.14.3.1, Restrictions]
3349 // Only a single default clause may be specified on a parallel, task or
3350 // teams directive.
3351 // OpenMP [2.5, parallel Construct, Restrictions]
3352 // At most one proc_bind clause can appear on the directive.
3353 // OpenMP [5.0, Requires directive, Restrictions]
3354 // At most one atomic_default_mem_order clause can appear
3355 // on the directive
3356 // OpenMP [5.1, error directive, Restrictions]
3357 // At most one at clause can appear on the directive
3358 // At most one severity clause can appear on the directive
3359 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3360 // At most one bind clause can appear on a loop directive.
3361 if (!FirstClause) {
3362 Diag(Tok, diag::err_omp_more_one_clause)
3363 << getOpenMPDirectiveName(DKind, OMPVersion)
3364 << getOpenMPClauseName(CKind) << 0;
3365 ErrorFound = true;
3366 }
3367
3368 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3369 break;
3370 case OMPC_device:
3371 case OMPC_schedule:
3372 case OMPC_dist_schedule:
3373 case OMPC_defaultmap:
3374 case OMPC_default:
3375 case OMPC_order:
3376 // OpenMP [2.7.1, Restrictions, p. 3]
3377 // Only one schedule clause can appear on a loop directive.
3378 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3379 // At most one defaultmap clause can appear on the directive.
3380 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3381 // At most one device clause can appear on the directive.
3382 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3383 // At most one order clause may appear on a construct.
3384 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3385 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3386 Diag(Tok, diag::err_omp_more_one_clause)
3387 << getOpenMPDirectiveName(DKind, OMPVersion)
3388 << getOpenMPClauseName(CKind) << 0;
3389 ErrorFound = true;
3390 }
3391 [[fallthrough]];
3392 case OMPC_if:
3393 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3394 break;
3395 case OMPC_holds:
3396 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3397 break;
3398 case OMPC_nowait:
3399 case OMPC_untied:
3400 case OMPC_mergeable:
3401 case OMPC_read:
3402 case OMPC_write:
3403 case OMPC_capture:
3404 case OMPC_compare:
3405 case OMPC_seq_cst:
3406 case OMPC_acq_rel:
3407 case OMPC_acquire:
3408 case OMPC_release:
3409 case OMPC_relaxed:
3410 case OMPC_weak:
3411 case OMPC_threads:
3412 case OMPC_simd:
3413 case OMPC_nogroup:
3414 case OMPC_unified_address:
3415 case OMPC_unified_shared_memory:
3416 case OMPC_reverse_offload:
3417 case OMPC_dynamic_allocators:
3418 case OMPC_full:
3419 // OpenMP [2.7.1, Restrictions, p. 9]
3420 // Only one ordered clause can appear on a loop directive.
3421 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3422 // Only one nowait clause can appear on a for directive.
3423 // OpenMP [5.0, Requires directive, Restrictions]
3424 // Each of the requires clauses can appear at most once on the directive.
3425 if (!FirstClause) {
3426 Diag(Tok, diag::err_omp_more_one_clause)
3427 << getOpenMPDirectiveName(DKind, OMPVersion)
3428 << getOpenMPClauseName(CKind) << 0;
3429 ErrorFound = true;
3430 }
3431
3432 if (CKind == OMPC_nowait && PP.LookAhead(/*N=*/0).is(tok::l_paren) &&
3433 getLangOpts().OpenMP >= 60)
3434 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3435 else
3436 Clause = ParseOpenMPClause(CKind, WrongDirective);
3437 break;
3438 case OMPC_self_maps:
3439 // OpenMP [6.0, self_maps clause]
3440 if (getLangOpts().OpenMP < 60) {
3441 Diag(Tok, diag::err_omp_expected_clause)
3442 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
3443 ErrorFound = true;
3444 }
3445 if (!FirstClause) {
3446 Diag(Tok, diag::err_omp_more_one_clause)
3447 << getOpenMPDirectiveName(DKind, OMPVersion)
3448 << getOpenMPClauseName(CKind) << 0;
3449 ErrorFound = true;
3450 }
3451 Clause = ParseOpenMPClause(CKind, WrongDirective);
3452 break;
3453 case OMPC_update:
3454 if (!FirstClause) {
3455 Diag(Tok, diag::err_omp_more_one_clause)
3456 << getOpenMPDirectiveName(DKind, OMPVersion)
3457 << getOpenMPClauseName(CKind) << 0;
3458 ErrorFound = true;
3459 }
3460 Clause = ParseOpenMPClause(CKind, WrongDirective);
3461 break;
3462 case OMPC_update_depend_objects:
3463 if (!FirstClause) {
3464 Diag(Tok, diag::err_omp_more_one_clause)
3465 << getOpenMPDirectiveName(DKind, OMPVersion)
3466 << getOpenMPClauseName(CKind) << 0;
3467 ErrorFound = true;
3468 }
3469
3470 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3471 break;
3472 case OMPC_num_teams:
3473 case OMPC_thread_limit:
3474 case OMPC_num_threads:
3475 if (!FirstClause) {
3476 Diag(Tok, diag::err_omp_more_one_clause)
3477 << getOpenMPDirectiveName(DKind, OMPVersion)
3478 << getOpenMPClauseName(CKind) << 0;
3479 ErrorFound = true;
3480 }
3481 [[fallthrough]];
3482 case OMPC_private:
3483 case OMPC_firstprivate:
3484 case OMPC_lastprivate:
3485 case OMPC_shared:
3486 case OMPC_reduction:
3487 case OMPC_task_reduction:
3488 case OMPC_in_reduction:
3489 case OMPC_linear:
3490 case OMPC_aligned:
3491 case OMPC_copyin:
3492 case OMPC_copyprivate:
3493 case OMPC_flush:
3494 case OMPC_depend:
3495 case OMPC_map:
3496 case OMPC_to:
3497 case OMPC_from:
3498 case OMPC_use_device_ptr:
3499 case OMPC_use_device_addr:
3500 case OMPC_is_device_ptr:
3501 case OMPC_has_device_addr:
3502 case OMPC_allocate:
3503 case OMPC_nontemporal:
3504 case OMPC_inclusive:
3505 case OMPC_exclusive:
3506 case OMPC_affinity:
3507 case OMPC_doacross:
3508 case OMPC_enter:
3509 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered_standalone &&
3510 CKind == OMPC_depend)
3511 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3512 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3513 break;
3514 case OMPC_sizes:
3515 if (!FirstClause) {
3516 Diag(Tok, diag::err_omp_more_one_clause)
3517 << getOpenMPDirectiveName(DKind, OMPVersion)
3518 << getOpenMPClauseName(CKind) << 0;
3519 ErrorFound = true;
3520 }
3521
3522 Clause = ParseOpenMPSizesClause();
3523 break;
3524 case OMPC_permutation:
3525 if (!FirstClause) {
3526 Diag(Tok, diag::err_omp_more_one_clause)
3527 << getOpenMPDirectiveName(DKind, OMPVersion)
3528 << getOpenMPClauseName(CKind) << 0;
3529 ErrorFound = true;
3530 }
3531 Clause = ParseOpenMPPermutationClause();
3532 break;
3533 case OMPC_counts:
3534 if (!FirstClause) {
3535 Diag(Tok, diag::err_omp_more_one_clause)
3536 << getOpenMPDirectiveName(DKind, OMPVersion)
3537 << getOpenMPClauseName(CKind) << 0;
3538 ErrorFound = true;
3539 }
3540 Clause = ParseOpenMPCountsClause();
3541 break;
3542 case OMPC_uses_allocators:
3543 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3544 break;
3545 case OMPC_destroy:
3546 if (DKind != OMPD_interop) {
3547 if (!FirstClause) {
3548 Diag(Tok, diag::err_omp_more_one_clause)
3549 << getOpenMPDirectiveName(DKind, OMPVersion)
3550 << getOpenMPClauseName(CKind) << 0;
3551 ErrorFound = true;
3552 }
3553 Clause = ParseOpenMPClause(CKind, WrongDirective);
3554 break;
3555 }
3556 [[fallthrough]];
3557 case OMPC_init:
3558 case OMPC_use:
3559 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3560 break;
3561 case OMPC_device_type:
3562 case OMPC_unknown:
3563 skipUntilPragmaOpenMPEnd(DKind);
3564 break;
3565 case OMPC_threadprivate:
3566 case OMPC_groupprivate:
3567 case OMPC_uniform:
3568 case OMPC_match:
3569 if (!WrongDirective)
3570 Diag(Tok, diag::err_omp_unexpected_clause)
3571 << getOpenMPClauseName(CKind)
3572 << getOpenMPDirectiveName(DKind, OMPVersion);
3573 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3574 break;
3575 case OMPC_absent:
3576 case OMPC_contains: {
3577 SourceLocation Loc = ConsumeToken();
3578 SourceLocation LLoc = Tok.getLocation();
3579 SourceLocation RLoc;
3580 llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
3581 BalancedDelimiterTracker T(*this, tok::l_paren);
3582 T.consumeOpen();
3583 do {
3584 OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
3585 if (DK == OMPD_unknown) {
3586 skipUntilPragmaOpenMPEnd(OMPD_assume);
3587 Diag(Tok, diag::err_omp_unexpected_clause)
3588 << getOpenMPClauseName(CKind)
3589 << getOpenMPDirectiveName(DKind, OMPVersion);
3590 break;
3591 }
3593 DKVec.push_back(DK);
3594 ConsumeToken();
3595 } else {
3596 Diag(Tok, diag::err_omp_unexpected_clause)
3597 << getOpenMPClauseName(CKind)
3598 << getOpenMPDirectiveName(DKind, OMPVersion);
3599 }
3600 } while (TryConsumeToken(tok::comma));
3601 RLoc = Tok.getLocation();
3602 T.consumeClose();
3603 if (!WrongDirective)
3604 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3605 CKind, DKVec, Loc, LLoc, RLoc);
3606 break;
3607 }
3608 case OMPC_no_openmp:
3609 case OMPC_no_openmp_routines:
3610 case OMPC_no_openmp_constructs:
3611 case OMPC_no_parallelism: {
3612 if (!FirstClause) {
3613 Diag(Tok, diag::err_omp_more_one_clause)
3614 << getOpenMPDirectiveName(DKind, OMPVersion)
3615 << getOpenMPClauseName(CKind) << 0;
3616 ErrorFound = true;
3617 }
3618 SourceLocation Loc = ConsumeToken();
3619 if (!WrongDirective)
3620 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3621 CKind, Loc, Tok.getLocation());
3622 break;
3623 }
3624 case OMPC_ompx_attribute:
3625 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3626 break;
3627 case OMPC_ompx_bare:
3628 if (DKind == llvm::omp::Directive::OMPD_target) {
3629 // Flang splits the combined directives which requires OMPD_target to be
3630 // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
3631 // to explicitly check whether this clause is applied to an `omp target`
3632 // without `teams` and emit an error.
3633 Diag(Tok, diag::err_omp_unexpected_clause)
3634 << getOpenMPClauseName(CKind)
3635 << getOpenMPDirectiveName(DKind, OMPVersion);
3636 ErrorFound = true;
3637 WrongDirective = true;
3638 }
3639 if (WrongDirective)
3640 Diag(Tok, diag::note_ompx_bare_clause)
3641 << getOpenMPClauseName(CKind) << "target teams";
3642 if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3643 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3644 << getOpenMPClauseName(CKind)
3645 << getOpenMPDirectiveName(DKind, OMPVersion);
3646 ErrorFound = true;
3647 }
3648 Clause = ParseOpenMPClause(CKind, WrongDirective);
3649 break;
3650 case OMPC_looprange:
3651 Clause = ParseOpenMPLoopRangeClause();
3652 break;
3653 default:
3654 break;
3655 }
3656 return ErrorFound ? nullptr : Clause;
3657}
3658
3659/// Parses simple expression in parens for single-expression clauses of OpenMP
3660/// constructs.
3661/// \param RLoc Returned location of right paren.
3663 SourceLocation &RLoc,
3664 bool IsAddressOfOperand) {
3665 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3666 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3667 return ExprError();
3668
3669 SourceLocation ELoc = Tok.getLocation();
3670 ExprResult LHS(
3671 ParseCastExpression(CastParseKind::AnyCastExpr, IsAddressOfOperand,
3673 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3674 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3675
3676 // Parse ')'.
3677 RLoc = Tok.getLocation();
3678 if (!T.consumeClose())
3679 RLoc = T.getCloseLocation();
3680
3681 return Val;
3682}
3683
3684OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3685 bool ParseOnly) {
3687 SourceLocation LLoc = Tok.getLocation();
3688 SourceLocation RLoc;
3689
3690 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3691
3692 if (Val.isInvalid())
3693 return nullptr;
3694
3695 if (ParseOnly)
3696 return nullptr;
3697 return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3698 LLoc, RLoc);
3699}
3700
3701bool Parser::ParseOpenMPIndirectClause(
3702 SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3704 SourceLocation RLoc;
3705
3706 if (Tok.isNot(tok::l_paren)) {
3707 if (ParseOnly)
3708 return false;
3709 DTCI.Indirect = nullptr;
3710 return true;
3711 }
3712
3713 ExprResult Val =
3714 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3715 if (Val.isInvalid())
3716 return false;
3717
3718 if (ParseOnly)
3719 return false;
3720
3721 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3722 !Val.get()->isInstantiationDependent() &&
3724 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3725 if (Ret.isInvalid())
3726 return false;
3727 llvm::APSInt Result;
3728 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3730 if (Ret.isInvalid())
3731 return false;
3732 DTCI.Indirect = Val.get();
3733 return true;
3734 }
3735 return false;
3736}
3737
3738ExprResult Parser::ParseOMPInteropFrSelector() {
3739 ConsumeToken(); // 'fr'
3740 BalancedDelimiterTracker FT(*this, tok::l_paren,
3741 tok::annot_pragma_openmp_end);
3742 if (FT.expectAndConsume(diag::err_expected_lparen_after, "fr")) {
3743 SkipUntil(
3744 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3746 return ExprError();
3747 }
3748 SourceLocation Loc = Tok.getLocation();
3749 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3750 ExprResult Arg = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3751 Arg = Actions.ActOnFinishFullExpr(Arg.get(), Loc, /*DiscardedValue=*/false);
3752 FT.consumeClose();
3753 return Arg;
3754}
3755
3756bool Parser::ParseOMPInteropAttrSelector(SmallVectorImpl<Expr *> &Attrs) {
3757 ConsumeToken(); // 'attr'
3758 BalancedDelimiterTracker AT(*this, tok::l_paren,
3759 tok::annot_pragma_openmp_end);
3760 if (AT.expectAndConsume(diag::err_expected_lparen_after, "attr")) {
3761 SkipUntil(
3762 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3764 return true;
3765 }
3766 bool HasError = false;
3767 // attr() requires at least one ext-string-literal argument; an empty list is
3768 // not permitted by the prefer_type grammar.
3769 if (Tok.is(tok::r_paren)) {
3770 Diag(Tok, diag::err_omp_interop_attr_not_string);
3771 HasError = true;
3772 }
3773 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::r_brace) &&
3774 Tok.isNot(tok::annot_pragma_openmp_end)) {
3775 if (Tok.is(tok::string_literal)) {
3777 if (S.isUsable())
3778 Attrs.push_back(S.get());
3779 else
3780 HasError = true;
3781 } else {
3782 HasError = true;
3783 Diag(Tok, diag::err_omp_interop_attr_not_string);
3784 ConsumeToken();
3785 }
3786 if (Tok.is(tok::comma))
3787 ConsumeToken();
3788 }
3789 AT.consumeClose();
3790 return HasError;
3791}
3792
3793bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3794 OpenMPClauseKind Kind) {
3795 const Token &Tok = getCurToken();
3796 bool HasError = false;
3797 bool IsTarget = false;
3798 bool IsTargetSync = false;
3799
3800 while (Tok.is(tok::identifier)) {
3801 // prefer_type is allowed with 'init' and 'append_args' and must be first.
3802 bool PreferTypeAllowed = (Kind == OMPC_init || Kind == OMPC_append_args) &&
3803 InteropInfo.Prefs.empty() && !IsTarget &&
3804 !IsTargetSync;
3805 if (Tok.getIdentifierInfo()->isStr("target")) {
3806 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3807 // Each interop-type may be specified on an action-clause at most
3808 // once.
3809 if (IsTarget)
3810 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3811 IsTarget = true;
3812 ConsumeToken();
3813 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3814 if (IsTargetSync)
3815 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3816 IsTargetSync = true;
3817 ConsumeToken();
3818 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3819 PreferTypeAllowed) {
3820 if (Kind == OMPC_append_args && getLangOpts().OpenMP < 60) {
3821 Diag(Tok, diag::err_omp_append_args_prefer_type_60);
3822 HasError = true;
3823 }
3824 ConsumeToken();
3825 BalancedDelimiterTracker PT(*this, tok::l_paren,
3826 tok::annot_pragma_openmp_end);
3827 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3828 HasError = true;
3829
3830 // prefer_type requires at least one preference-specification.
3831 if (Tok.is(tok::r_paren)) {
3832 Diag(Tok, diag::err_omp_expected_pref_spec);
3833 HasError = true;
3834 }
3835
3836 while (Tok.isNot(tok::r_paren) &&
3837 Tok.isNot(tok::annot_pragma_openmp_end)) {
3838 // OMP 6.0: { fr(...), attr(...) } brace-grouped pref-spec
3839 if (Tok.is(tok::l_brace)) {
3840 // The brace-grouped form was introduced in OpenMP 6.0; earlier
3841 // versions only allow the flat foreign-runtime-id list.
3842 if (getLangOpts().OpenMP < 60) {
3843 Diag(Tok, diag::err_omp_prefer_type_brace_60);
3844 HasError = true;
3845 }
3846 BalancedDelimiterTracker BT(*this, tok::l_brace,
3847 tok::annot_pragma_openmp_end);
3848 BT.consumeOpen();
3849 Expr *FrExpr = nullptr;
3850 SmallVector<Expr *, 2> AttrExprs;
3851 bool SeenFr = false;
3852
3853 // A pref-spec requires at least one 'fr'/'attr' selector; {} is not
3854 // permitted by the grammar.
3855 if (Tok.is(tok::r_brace)) {
3856 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3857 HasError = true;
3858 }
3859
3860 while (Tok.isNot(tok::r_brace) &&
3861 Tok.isNot(tok::annot_pragma_openmp_end)) {
3862 if (Tok.is(tok::identifier) &&
3863 Tok.getIdentifierInfo()->isStr("fr")) {
3864 if (SeenFr) {
3865 Diag(Tok, diag::err_omp_interop_multiple_fr);
3866 HasError = true;
3867 ConsumeToken(); // 'fr'
3868 SkipUntil(
3869 {tok::comma, tok::r_brace, tok::annot_pragma_openmp_end},
3871 continue;
3872 }
3873 SeenFr = true;
3874 ExprResult Fr = ParseOMPInteropFrSelector();
3875 if (Fr.isUsable())
3876 FrExpr = Fr.get();
3877 else
3878 HasError = true;
3879 } else if (Tok.is(tok::identifier) &&
3880 Tok.getIdentifierInfo()->isStr("attr")) {
3881 if (ParseOMPInteropAttrSelector(AttrExprs))
3882 HasError = true;
3883 } else {
3884 // Neither 'fr' nor 'attr' (a non-identifier or some other word).
3885 HasError = true;
3886 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3887 ConsumeToken();
3888 }
3889 if (Tok.is(tok::comma))
3890 ConsumeToken();
3891 }
3892 if (BT.consumeClose())
3893 HasError = true;
3894
3895 if (FrExpr || !AttrExprs.empty())
3896 InteropInfo.Prefs.emplace_back(FrExpr, AttrExprs);
3897 InteropInfo.HasPreferAttrs = true;
3898 } else {
3899 // OMP 5.1: flat foreign-runtime-id (string or int). Stored as a
3900 // pref-spec with Fr=expr and no attr() entries.
3901 SourceLocation Loc = Tok.getLocation();
3902 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3903 ExprResult PTExpr =
3904 ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3905 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3906 /*DiscardedValue=*/false);
3907 if (PTExpr.isUsable()) {
3908 InteropInfo.Prefs.emplace_back(PTExpr.get(),
3909 llvm::SmallVector<Expr *, 2>{});
3910 } else {
3911 HasError = true;
3912 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3914 }
3915 }
3916
3917 if (Tok.is(tok::comma))
3918 ConsumeToken();
3919 }
3920 PT.consumeClose();
3921 } else {
3922 HasError = true;
3923 Diag(Tok, diag::err_omp_expected_interop_type);
3924 ConsumeToken();
3925 }
3926 if (!Tok.is(tok::comma))
3927 break;
3928 ConsumeToken();
3929 }
3930
3931 if (!HasError && !IsTarget && !IsTargetSync) {
3932 Diag(Tok, diag::err_omp_expected_interop_type);
3933 HasError = true;
3934 }
3935
3936 if (Kind == OMPC_init) {
3937 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3938 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3939 if (Tok.is(tok::colon))
3940 ConsumeToken();
3941 }
3942
3943 // As of OpenMP 5.1,there are two interop-types, "target" and
3944 // "targetsync". Either or both are allowed for a single interop.
3945 InteropInfo.IsTarget = IsTarget;
3946 InteropInfo.IsTargetSync = IsTargetSync;
3947
3948 return HasError;
3949}
3950
3951OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3952 bool ParseOnly) {
3953 SourceLocation Loc = ConsumeToken();
3954 // Parse '('.
3955 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3956 if (T.expectAndConsume(diag::err_expected_lparen_after,
3957 getOpenMPClauseName(Kind).data()))
3958 return nullptr;
3959
3960 bool InteropError = false;
3961 OMPInteropInfo InteropInfo;
3962 if (Kind == OMPC_init)
3963 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3964
3965 // Parse the variable.
3966 SourceLocation VarLoc = Tok.getLocation();
3967 ExprResult InteropVarExpr = ParseAssignmentExpression();
3968 if (!InteropVarExpr.isUsable()) {
3969 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3971 }
3972
3973 // Parse ')'.
3974 SourceLocation RLoc = Tok.getLocation();
3975 if (!T.consumeClose())
3976 RLoc = T.getCloseLocation();
3977
3978 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3979 return nullptr;
3980
3981 if (Kind == OMPC_init)
3982 return Actions.OpenMP().ActOnOpenMPInitClause(
3983 InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3984 RLoc);
3985 if (Kind == OMPC_use)
3986 return Actions.OpenMP().ActOnOpenMPUseClause(
3987 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3988
3989 if (Kind == OMPC_destroy)
3990 return Actions.OpenMP().ActOnOpenMPDestroyClause(
3991 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3992
3993 llvm_unreachable("Unexpected interop variable clause.");
3994}
3995
3996OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3997 SourceLocation Loc = ConsumeToken();
3998 // Parse '('.
3999 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4000 if (T.expectAndConsume(diag::err_expected_lparen_after,
4001 getOpenMPClauseName(OMPC_ompx_attribute).data()))
4002 return nullptr;
4003
4004 ParsedAttributes ParsedAttrs(AttrFactory);
4005 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
4006
4007 // Parse ')'.
4008 if (T.consumeClose())
4009 return nullptr;
4010
4011 if (ParseOnly)
4012 return nullptr;
4013
4014 SmallVector<Attr *> Attrs;
4015 for (const ParsedAttr &PA : ParsedAttrs) {
4016 switch (PA.getKind()) {
4017 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
4018 if (!PA.checkExactlyNumArgs(Actions, 2))
4019 continue;
4020 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
4021 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
4022 Attrs.push_back(A);
4023 continue;
4024 case ParsedAttr::AT_AMDGPUWavesPerEU:
4025 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
4026 !PA.checkAtMostNumArgs(Actions, 2))
4027 continue;
4028 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
4029 PA, PA.getArgAsExpr(0),
4030 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
4031 Attrs.push_back(A);
4032 continue;
4033 case ParsedAttr::AT_CUDALaunchBounds:
4034 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
4035 !PA.checkAtMostNumArgs(Actions, 3))
4036 continue;
4037 if (auto *A = Actions.CreateLaunchBoundsAttr(
4038 PA, PA.getArgAsExpr(0),
4039 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
4040 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr,
4041 /*IgnoreArch=*/true))
4042 Attrs.push_back(A);
4043 continue;
4044 default:
4045 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
4046 continue;
4047 };
4048 }
4049
4050 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
4051 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
4052}
4053
4054OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
4055 bool ParseOnly) {
4056 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
4057 if (!Val || ParseOnly)
4058 return nullptr;
4059 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
4060 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
4061 static_cast<DefaultKind>(Val->Type) ==
4062 OMP_DEFAULT_firstprivate)) {
4063 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
4064 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
4065 OMP_DEFAULT_private
4066 ? OMPC_private
4067 : OMPC_firstprivate)
4068 << getOpenMPClauseName(OMPC_default) << "5.1";
4069 return nullptr;
4070 }
4071 return Actions.OpenMP().ActOnOpenMPSimpleClause(
4072 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
4073}
4074
4075OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
4076 SourceLocation Loc = Tok.getLocation();
4078
4079 if (ParseOnly)
4080 return nullptr;
4081 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
4082}
4083
4084OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
4085 OpenMPClauseKind Kind,
4086 bool ParseOnly) {
4087 SourceLocation Loc = ConsumeToken();
4088 SourceLocation DelimLoc;
4089 // Parse '('.
4090 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4091 if (T.expectAndConsume(diag::err_expected_lparen_after,
4092 getOpenMPClauseName(Kind).data()))
4093 return nullptr;
4094
4095 ExprResult Val;
4096 SmallVector<unsigned, 4> Arg;
4097 SmallVector<SourceLocation, 4> KLoc;
4098 if (Kind == OMPC_schedule) {
4099 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
4100 Arg.resize(NumberOfElements);
4101 KLoc.resize(NumberOfElements);
4102 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
4103 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
4104 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
4105 unsigned KindModifier = getOpenMPSimpleClauseType(
4106 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4107 if (KindModifier > OMPC_SCHEDULE_unknown) {
4108 // Parse 'modifier'
4109 Arg[Modifier1] = KindModifier;
4110 KLoc[Modifier1] = Tok.getLocation();
4111 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4112 Tok.isNot(tok::annot_pragma_openmp_end))
4114 if (Tok.is(tok::comma)) {
4115 // Parse ',' 'modifier'
4117 KindModifier = getOpenMPSimpleClauseType(
4118 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4119 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
4120 ? KindModifier
4121 : (unsigned)OMPC_SCHEDULE_unknown;
4122 KLoc[Modifier2] = Tok.getLocation();
4123 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4124 Tok.isNot(tok::annot_pragma_openmp_end))
4126 }
4127 // Parse ':'
4128 if (Tok.is(tok::colon))
4130 else
4131 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
4132 KindModifier = getOpenMPSimpleClauseType(
4133 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4134 }
4135 Arg[ScheduleKind] = KindModifier;
4136 KLoc[ScheduleKind] = Tok.getLocation();
4137 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4138 Tok.isNot(tok::annot_pragma_openmp_end))
4140 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
4141 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
4142 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
4143 Tok.is(tok::comma))
4144 DelimLoc = ConsumeAnyToken();
4145 } else if (Kind == OMPC_dist_schedule) {
4146 Arg.push_back(getOpenMPSimpleClauseType(
4147 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4148 KLoc.push_back(Tok.getLocation());
4149 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4150 Tok.isNot(tok::annot_pragma_openmp_end))
4152 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
4153 DelimLoc = ConsumeAnyToken();
4154 } else if (Kind == OMPC_default) {
4155 // Get a default modifier
4156 unsigned Modifier = getOpenMPSimpleClauseType(
4157 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4158
4159 Arg.push_back(Modifier);
4160 KLoc.push_back(Tok.getLocation());
4161 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4162 Tok.isNot(tok::annot_pragma_openmp_end))
4164 // Parse ':'
4165 if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {
4167 // Get a variable-category attribute for default clause modifier
4168 OpenMPDefaultClauseVariableCategory VariableCategory =
4170 Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4171 Arg.push_back(VariableCategory);
4172 KLoc.push_back(Tok.getLocation());
4173 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4174 Tok.isNot(tok::annot_pragma_openmp_end))
4176 } else {
4177 Arg.push_back(OMPC_DEFAULT_VC_all);
4178 KLoc.push_back(SourceLocation());
4179 }
4180 } else if (Kind == OMPC_defaultmap) {
4181 // Get a defaultmap modifier
4182 unsigned Modifier = getOpenMPSimpleClauseType(
4183 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4184
4185 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
4186 // pointer
4187 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
4189 Arg.push_back(Modifier);
4190 KLoc.push_back(Tok.getLocation());
4191 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4192 Tok.isNot(tok::annot_pragma_openmp_end))
4194 // Parse ':'
4195 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
4196 if (Tok.is(tok::colon))
4198 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
4199 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
4200 // Get a defaultmap kind
4201 Arg.push_back(getOpenMPSimpleClauseType(
4202 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4203 KLoc.push_back(Tok.getLocation());
4204 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4205 Tok.isNot(tok::annot_pragma_openmp_end))
4207 } else {
4208 Arg.push_back(OMPC_DEFAULTMAP_unknown);
4209 KLoc.push_back(SourceLocation());
4210 }
4211 } else if (Kind == OMPC_order) {
4212 enum { Modifier, OrderKind, NumberOfElements };
4213 Arg.resize(NumberOfElements);
4214 KLoc.resize(NumberOfElements);
4215 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
4216 Arg[OrderKind] = OMPC_ORDER_unknown;
4217 unsigned KindModifier = getOpenMPSimpleClauseType(
4218 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4219 if (KindModifier > OMPC_ORDER_unknown) {
4220 // Parse 'modifier'
4221 Arg[Modifier] = KindModifier;
4222 KLoc[Modifier] = Tok.getLocation();
4223 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4224 Tok.isNot(tok::annot_pragma_openmp_end))
4226 // Parse ':'
4227 if (Tok.is(tok::colon))
4229 else
4230 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
4231 KindModifier = getOpenMPSimpleClauseType(
4232 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4233 }
4234 Arg[OrderKind] = KindModifier;
4235 KLoc[OrderKind] = Tok.getLocation();
4236 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4237 Tok.isNot(tok::annot_pragma_openmp_end))
4239 } else if (Kind == OMPC_device) {
4240 // Only target executable directives support extended device construct.
4241 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4242 NextToken().is(tok::colon)) {
4243 // Parse optional <device modifier> ':'
4244 Arg.push_back(getOpenMPSimpleClauseType(
4245 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4246 KLoc.push_back(Tok.getLocation());
4248 // Parse ':'
4250 } else {
4251 Arg.push_back(OMPC_DEVICE_unknown);
4252 KLoc.emplace_back();
4253 }
4254 } else if (Kind == OMPC_grainsize) {
4255 // Parse optional <grainsize modifier> ':'
4258 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4259 getLangOpts()));
4260 if (getLangOpts().OpenMP >= 51) {
4261 if (NextToken().is(tok::colon)) {
4262 Arg.push_back(Modifier);
4263 KLoc.push_back(Tok.getLocation());
4264 // Parse modifier
4266 // Parse ':'
4268 } else {
4269 if (Modifier == OMPC_GRAINSIZE_strict) {
4270 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4271 // Parse modifier
4273 }
4274 Arg.push_back(OMPC_GRAINSIZE_unknown);
4275 KLoc.emplace_back();
4276 }
4277 } else {
4278 Arg.push_back(OMPC_GRAINSIZE_unknown);
4279 KLoc.emplace_back();
4280 }
4281 } else if (Kind == OMPC_dyn_groupprivate) {
4282 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
4283 Arg.resize(NumberOfModifiers);
4284 KLoc.resize(NumberOfModifiers);
4285 Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
4286 Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
4287
4288 auto ConsumeModifier = [&]() {
4289 unsigned Type = NumberOfModifiers;
4290 unsigned Modifier;
4291 SourceLocation Loc;
4292 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
4293 NextToken().is(tok::l_paren)) {
4294 ConsumeToken();
4295 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4296 ParenT.consumeOpen();
4297
4298 Modifier = getOpenMPSimpleClauseType(
4299 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4302 Diag(Tok.getLocation(), diag::err_expected)
4303 << "'abort', 'null' or 'default_mem' in fallback modifier";
4304 SkipUntil(tok::r_paren);
4305 return std::make_tuple(Type, Modifier, Loc);
4306 }
4307 Type = ComplexModifier;
4308 Loc = Tok.getLocation();
4309 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4310 Tok.isNot(tok::annot_pragma_openmp_end))
4312 ParenT.consumeClose();
4313 } else {
4314 Modifier = getOpenMPSimpleClauseType(
4315 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4316 if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
4317 Type = SimpleModifier;
4318 Loc = Tok.getLocation();
4319 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4320 Tok.isNot(tok::annot_pragma_openmp_end))
4322 }
4323 }
4324 return std::make_tuple(Type, Modifier, Loc);
4325 };
4326
4327 auto SaveModifier = [&](unsigned Type, unsigned Modifier,
4328 SourceLocation Loc) {
4329 assert(Type < NumberOfModifiers && "Unexpected modifier type");
4330 if (!KLoc[Type].isValid()) {
4331 Arg[Type] = Modifier;
4332 KLoc[Type] = Loc;
4333 } else {
4334 Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
4335 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
4336 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
4337 }
4338 };
4339
4340 // Parse 'modifier'
4341 auto [Type1, Mod1, Loc1] = ConsumeModifier();
4342 if (Type1 < NumberOfModifiers) {
4343 SaveModifier(Type1, Mod1, Loc1);
4344 if (Tok.is(tok::comma)) {
4345 // Parse ',' 'modifier'
4347 auto [Type2, Mod2, Loc2] = ConsumeModifier();
4348 if (Type2 < NumberOfModifiers)
4349 SaveModifier(Type2, Mod2, Loc2);
4350 }
4351 // Parse ':'
4352 if (Tok.is(tok::colon))
4354 else
4355 Diag(Tok, diag::warn_pragma_expected_colon)
4356 << "dyn_groupprivate modifier";
4357 }
4358 } else if (Kind == OMPC_num_tasks) {
4359 // Parse optional <num_tasks modifier> ':'
4362 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4363 getLangOpts()));
4364 if (getLangOpts().OpenMP >= 51) {
4365 if (NextToken().is(tok::colon)) {
4366 Arg.push_back(Modifier);
4367 KLoc.push_back(Tok.getLocation());
4368 // Parse modifier
4370 // Parse ':'
4372 } else {
4373 if (Modifier == OMPC_NUMTASKS_strict) {
4374 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4375 // Parse modifier
4377 }
4378 Arg.push_back(OMPC_NUMTASKS_unknown);
4379 KLoc.emplace_back();
4380 }
4381 } else {
4382 Arg.push_back(OMPC_NUMTASKS_unknown);
4383 KLoc.emplace_back();
4384 }
4385 } else {
4386 assert(Kind == OMPC_if);
4387 KLoc.push_back(Tok.getLocation());
4388 TentativeParsingAction TPA(*this);
4389 auto DK = parseOpenMPDirectiveKind(*this);
4390 Arg.push_back(static_cast<unsigned>(DK));
4391 if (DK != OMPD_unknown) {
4392 ConsumeToken();
4393 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4394 TPA.Commit();
4395 DelimLoc = ConsumeToken();
4396 } else {
4397 TPA.Revert();
4398 Arg.back() = unsigned(OMPD_unknown);
4399 }
4400 } else {
4401 TPA.Revert();
4402 }
4403 }
4404
4405 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4406 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
4407 Kind == OMPC_if || Kind == OMPC_device ||
4408 Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
4409 Kind == OMPC_dyn_groupprivate;
4410 if (NeedAnExpression) {
4411 SourceLocation ELoc = Tok.getLocation();
4412 ExprResult LHS(
4413 ParseCastExpression(CastParseKind::AnyCastExpr, false,
4415 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4416 Val =
4417 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4418 }
4419
4420 // Parse ')'.
4421 SourceLocation RLoc = Tok.getLocation();
4422 if (!T.consumeClose())
4423 RLoc = T.getCloseLocation();
4424
4425 if (NeedAnExpression && Val.isInvalid())
4426 return nullptr;
4427
4428 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
4429 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
4430 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
4431 Diag(KLoc[0], diag::err_omp_invalid_dsa)
4432 << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==
4433 OMP_DEFAULT_private
4434 ? OMPC_private
4435 : OMPC_firstprivate)
4436 << getOpenMPClauseName(OMPC_default) << "5.1";
4437 return nullptr;
4438 }
4439
4440 if (ParseOnly)
4441 return nullptr;
4442 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4443 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4444}
4445
4446static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4447 UnqualifiedId &ReductionId) {
4448 if (ReductionIdScopeSpec.isEmpty()) {
4449 auto OOK = OO_None;
4450 switch (P.getCurToken().getKind()) {
4451 case tok::plus:
4452 OOK = OO_Plus;
4453 break;
4454 case tok::minus:
4455 OOK = OO_Minus;
4456 break;
4457 case tok::star:
4458 OOK = OO_Star;
4459 break;
4460 case tok::amp:
4461 OOK = OO_Amp;
4462 break;
4463 case tok::pipe:
4464 OOK = OO_Pipe;
4465 break;
4466 case tok::caret:
4467 OOK = OO_Caret;
4468 break;
4469 case tok::ampamp:
4470 OOK = OO_AmpAmp;
4471 break;
4472 case tok::pipepipe:
4473 OOK = OO_PipePipe;
4474 break;
4475 default:
4476 break;
4477 }
4478 if (OOK != OO_None) {
4479 SourceLocation OpLoc = P.ConsumeToken();
4480 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4481 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4482 return false;
4483 }
4484 }
4485 return P.ParseUnqualifiedId(
4486 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4487 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4488 /*AllowDestructorName*/ false,
4489 /*AllowConstructorName*/ false,
4490 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4491}
4492
4493/// Checks if the token is a valid map-type-modifier.
4494/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4496 Token Tok = P.getCurToken();
4497 if (!Tok.is(tok::identifier))
4499
4500 Preprocessor &PP = P.getPreprocessor();
4501 OpenMPMapModifierKind TypeModifier =
4503 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4504 return TypeModifier;
4505}
4506
4508 // Parse '('.
4509 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4510 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4511 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4513 return true;
4514 }
4515 // Parse mapper-identifier
4516 if (getLangOpts().CPlusPlus)
4517 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4518 /*ObjectType=*/nullptr,
4519 /*ObjectHasErrors=*/false,
4520 /*EnteringContext=*/false);
4521 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4522 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4523 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4525 return true;
4526 }
4527 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4528 Data.ReductionOrMapperId = DeclarationNameInfo(
4529 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4530 ConsumeToken();
4531 // Parse ')'.
4532 return T.consumeClose();
4533}
4534
4536
4538 bool HasMapType = false;
4539 SourceLocation PreMapLoc = Tok.getLocation();
4540 StringRef PreMapName = "";
4541 while (getCurToken().isNot(tok::colon)) {
4542 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4543 OpenMPMapClauseKind MapKind = isMapType(*this);
4544 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4545 TypeModifier == OMPC_MAP_MODIFIER_close ||
4546 TypeModifier == OMPC_MAP_MODIFIER_present ||
4547 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4548 Data.MapTypeModifiers.push_back(TypeModifier);
4549 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4550 if (PP.LookAhead(0).isNot(tok::comma) &&
4551 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4552 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4553 << "map type modifier";
4554 ConsumeToken();
4555 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4556 Data.MapTypeModifiers.push_back(TypeModifier);
4557 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4558 ConsumeToken();
4560 return true;
4561 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4562 getLangOpts().OpenMP >= 52)
4563 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4564 << "map type modifier";
4565
4566 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4567 if (!HasMapType) {
4568 HasMapType = true;
4569 Data.ExtraModifier = MapKind;
4570 MapKind = OMPC_MAP_unknown;
4571 PreMapLoc = Tok.getLocation();
4572 PreMapName = Tok.getIdentifierInfo()->getName();
4573 } else {
4574 Diag(Tok, diag::err_omp_more_one_map_type);
4575 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4576 << PreMapName;
4577 }
4578 ConsumeToken();
4579 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
4580 Data.MapTypeModifiers.push_back(TypeModifier);
4581 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4582 if (PP.LookAhead(0).isNot(tok::comma) &&
4583 PP.LookAhead(0).isNot(tok::colon))
4584 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4585 << "map type modifier";
4586 if (getLangOpts().OpenMP < 60)
4587 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4588 << (getLangOpts().OpenMP >= 51
4589 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4590 : 0)
4591 << getLangOpts().OpenMPExtensions << 0;
4592 ConsumeToken();
4593 } else {
4594 // For the case of unknown map-type-modifier or a map-type.
4595 // Map-type is followed by a colon; the function returns when it
4596 // encounters a token followed by a colon.
4597 if (Tok.is(tok::comma)) {
4598 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4599 ConsumeToken();
4600 continue;
4601 }
4602 // Potential map-type token as it is followed by a colon.
4603 if (PP.LookAhead(0).is(tok::colon)) {
4604 if (getLangOpts().OpenMP >= 60) {
4605 break;
4606 } else {
4607 return false;
4608 }
4609 }
4610
4611 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4612 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4613 : 0)
4614 << getLangOpts().OpenMPExtensions
4615 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
4616 ConsumeToken();
4617 }
4618 if (getCurToken().is(tok::comma))
4619 ConsumeToken();
4620 }
4621 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4622 if (!Tok.is(tok::colon)) {
4623 Diag(Tok, diag::err_omp_unknown_map_type);
4624 ConsumeToken();
4625 } else {
4626 Data.ExtraModifier = OMPC_MAP_unknown;
4627 }
4628 }
4629 return false;
4630}
4631
4632/// Checks if the token is a valid map-type.
4633/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4635 Token Tok = P.getCurToken();
4636 // The map-type token can be either an identifier or the C++ delete keyword.
4637 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4638 return OMPC_MAP_unknown;
4639 Preprocessor &PP = P.getPreprocessor();
4640 unsigned MapType =
4642 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4643 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4644 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4645 return static_cast<OpenMPMapClauseKind>(MapType);
4646 return OMPC_MAP_unknown;
4647}
4648
4649/// Parse map-type in map clause.
4650/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4651/// where, map-type ::= to | from | tofrom | alloc | release | delete
4653 Token Tok = P.getCurToken();
4654 if (Tok.is(tok::colon)) {
4655 P.Diag(Tok, diag::err_omp_map_type_missing);
4656 return;
4657 }
4658 Data.ExtraModifier = isMapType(P);
4659 if (Data.ExtraModifier == OMPC_MAP_unknown)
4660 P.Diag(Tok, diag::err_omp_unknown_map_type);
4661 P.ConsumeToken();
4662}
4663
4664ExprResult Parser::ParseOpenMPIteratorsExpr() {
4665 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4666 "Expected 'iterator' token.");
4667 SourceLocation IteratorKwLoc = ConsumeToken();
4668
4669 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4670 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4671 return ExprError();
4672
4673 SourceLocation LLoc = T.getOpenLocation();
4674 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4675 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4676 // Check if the type parsing is required.
4677 ParsedType IteratorType;
4678 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4679 // identifier '=' is not found - parse type.
4681 if (TR.isInvalid()) {
4682 T.skipToEnd();
4683 return ExprError();
4684 }
4685 IteratorType = TR.get();
4686 }
4687
4688 // Parse identifier.
4689 IdentifierInfo *II = nullptr;
4690 SourceLocation IdLoc;
4691 if (Tok.is(tok::identifier)) {
4692 II = Tok.getIdentifierInfo();
4693 IdLoc = ConsumeToken();
4694 } else {
4695 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4696 }
4697
4698 // Parse '='.
4699 SourceLocation AssignLoc;
4700 if (Tok.is(tok::equal))
4701 AssignLoc = ConsumeToken();
4702 else
4703 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4704
4705 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4706 ColonProtectionRAIIObject ColonRAII(*this);
4707 // Parse <begin>
4708 SourceLocation Loc = Tok.getLocation();
4709 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4710 ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4711 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4712 /*DiscardedValue=*/false);
4713 // Parse ':'.
4714 SourceLocation ColonLoc;
4715 if (Tok.is(tok::colon))
4716 ColonLoc = ConsumeToken();
4717
4718 // Parse <end>
4719 Loc = Tok.getLocation();
4720 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4721 ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4722 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4723 /*DiscardedValue=*/false);
4724
4725 SourceLocation SecColonLoc;
4726 ExprResult Step;
4727 // Parse optional step.
4728 if (Tok.is(tok::colon)) {
4729 // Parse ':'
4730 SecColonLoc = ConsumeToken();
4731 // Parse <step>
4732 Loc = Tok.getLocation();
4733 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4734 Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4735 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4736 /*DiscardedValue=*/false);
4737 }
4738
4739 // Parse ',' or ')'
4740 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4741 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4742 if (Tok.is(tok::comma))
4743 ConsumeToken();
4744
4745 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4746 D.DeclIdent = II;
4747 D.DeclIdentLoc = IdLoc;
4748 D.Type = IteratorType;
4749 D.AssignLoc = AssignLoc;
4750 D.ColonLoc = ColonLoc;
4751 D.SecColonLoc = SecColonLoc;
4752 D.Range.Begin = Begin.get();
4753 D.Range.End = End.get();
4754 D.Range.Step = Step.get();
4755 }
4756
4757 // Parse ')'.
4758 SourceLocation RLoc = Tok.getLocation();
4759 if (!T.consumeClose())
4760 RLoc = T.getCloseLocation();
4761
4762 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4763 LLoc, RLoc, Data);
4764}
4765
4768 const LangOptions &LangOpts) {
4769 // Currently the only reserved locator is 'omp_all_memory' which is only
4770 // allowed on a depend clause.
4771 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4772 return false;
4773
4774 if (Tok.is(tok::identifier) &&
4775 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4776
4777 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4778 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4779 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4780 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4781 Data.ExtraModifier != OMPC_DEPEND_inout)
4782 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4783 else
4784 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4785 ? OMPC_DEPEND_outallmemory
4786 : OMPC_DEPEND_inoutallmemory;
4787 ConsumeToken();
4788 return true;
4789 }
4790 return false;
4791}
4792
4793/// Parse step size expression. Returns true if parsing is successfull,
4794/// otherwise returns false.
4796 OpenMPClauseKind CKind, SourceLocation ELoc) {
4798 Sema &Actions = P.getActions();
4799 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4800 /*DiscardedValue*/ false);
4801 if (Tail.isUsable()) {
4802 Data.DepModOrTailExpr = Tail.get();
4803 Token CurTok = P.getCurToken();
4804 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4805 P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4806 }
4807 return true;
4808 }
4809 return false;
4810}
4811
4812/// Parse 'allocate' clause modifiers.
4813/// If allocator-modifier exists, return an expression for it. For both
4814/// allocator and align modifiers, set Data fields as appropriate.
4815static ExprResult
4818 const Token &Tok = P.getCurToken();
4819 Preprocessor &PP = P.getPreprocessor();
4820 ExprResult Tail;
4821 ExprResult Val;
4822 SourceLocation RLoc;
4823 bool AllocatorSeen = false;
4824 bool AlignSeen = false;
4825 SourceLocation CurrentModifierLoc = Tok.getLocation();
4826 auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4828
4829 // Modifiers did not exist before 5.1
4830 if (P.getLangOpts().OpenMP < 51)
4831 return P.ParseAssignmentExpression();
4832
4833 // An allocator-simple-modifier is exclusive and must appear alone. See
4834 // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
4835 // description of "exclusive" property. If we don't recognized an explicit
4836 // simple-/complex- modifier, assume we're looking at expression
4837 // representing allocator and consider ourselves done.
4838 if (CurrentModifier == OMPC_ALLOCATE_unknown)
4839 return P.ParseAssignmentExpression();
4840
4841 do {
4842 P.ConsumeToken();
4843 if (Tok.is(tok::l_paren)) {
4844 switch (CurrentModifier) {
4845 case OMPC_ALLOCATE_allocator: {
4846 if (AllocatorSeen) {
4847 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4848 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4849 << getOpenMPClauseName(Kind);
4850 } else {
4851 Data.AllocClauseModifiers.push_back(CurrentModifier);
4852 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4853 }
4854 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
4855 tok::annot_pragma_openmp_end);
4856 AllocateT.consumeOpen();
4857 Tail = P.ParseAssignmentExpression();
4858 AllocateT.consumeClose();
4859 AllocatorSeen = true;
4860 break;
4861 }
4862 case OMPC_ALLOCATE_align: {
4863 if (AlignSeen) {
4864 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4865 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4866 << getOpenMPClauseName(Kind);
4867 } else {
4868 Data.AllocClauseModifiers.push_back(CurrentModifier);
4869 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4870 }
4871 Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
4872 if (Val.isUsable())
4873 Data.AllocateAlignment = Val.get();
4874 AlignSeen = true;
4875 break;
4876 }
4877 default:
4878 llvm_unreachable("Unexpected allocate modifier");
4879 }
4880 } else {
4881 P.Diag(Tok, diag::err_expected) << tok::l_paren;
4882 }
4883 if (Tok.isNot(tok::comma))
4884 break;
4885 P.ConsumeToken();
4886 CurrentModifierLoc = Tok.getLocation();
4887 CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4889 // A modifier followed by a comma implies another modifier.
4890 if (CurrentModifier == OMPC_ALLOCATE_unknown) {
4891 P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
4892 break;
4893 }
4894 } while (!AllocatorSeen || !AlignSeen);
4895 return Tail;
4896}
4897
4899 OpenMPClauseKind Kind,
4902 UnqualifiedId UnqualifiedReductionId;
4903 bool InvalidReductionId = false;
4904 bool IsInvalidMapperModifier = false;
4905
4906 // Parse '('.
4907 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4908 if (T.expectAndConsume(diag::err_expected_lparen_after,
4909 getOpenMPClauseName(Kind).data()))
4910 return true;
4911
4912 bool HasIterator = false;
4913 bool InvalidIterator = false;
4914 bool NeedRParenForLinear = false;
4915 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4916 tok::annot_pragma_openmp_end);
4917 // Handle reduction-identifier for reduction clause.
4918 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4919 Kind == OMPC_in_reduction) {
4920 Data.ExtraModifier = OMPC_REDUCTION_unknown;
4921 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4922 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4923 NextToken().is(tok::comma)) {
4924 // Parse optional reduction modifier.
4925 Data.ExtraModifier =
4926 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4927 Data.ExtraModifierLoc = Tok.getLocation();
4928 ConsumeToken();
4929 assert(Tok.is(tok::comma) && "Expected comma.");
4930 (void)ConsumeToken();
4931 }
4932 // Handle original(private / shared) Modifier
4933 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
4934 Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
4935 NextToken().is(tok::l_paren)) {
4936 // Parse original(private) modifier.
4937 ConsumeToken();
4938 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4939 ParenT.consumeOpen();
4940 if (Tok.is(tok::kw_private)) {
4941 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
4942 Data.OriginalSharingModifierLoc = Tok.getLocation();
4943 ConsumeToken();
4944 } else if (Tok.is(tok::identifier) &&
4945 (PP.getSpelling(Tok) == "shared" ||
4946 PP.getSpelling(Tok) == "default")) {
4947 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
4948 Data.OriginalSharingModifierLoc = Tok.getLocation();
4949 ConsumeToken();
4950 } else {
4951 Diag(Tok.getLocation(), diag::err_expected)
4952 << "'private or shared or default'";
4953 SkipUntil(tok::r_paren);
4954 return false;
4955 }
4956 ParenT.consumeClose();
4957 if (!Tok.is(tok::comma)) {
4958 Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
4959 return false;
4960 }
4961 (void)ConsumeToken();
4962 }
4963 ColonProtectionRAIIObject ColonRAII(*this);
4964 if (getLangOpts().CPlusPlus)
4965 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4966 /*ObjectType=*/nullptr,
4967 /*ObjectHasErrors=*/false,
4968 /*EnteringContext=*/false);
4969 InvalidReductionId = ParseReductionId(
4970 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4971 if (InvalidReductionId) {
4972 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4974 }
4975 if (Tok.is(tok::colon))
4976 Data.ColonLoc = ConsumeToken();
4977 else
4978 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4979 if (!InvalidReductionId)
4980 Data.ReductionOrMapperId =
4981 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4982 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4983 if (getLangOpts().OpenMP >= 50) {
4984 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4985 // Handle optional dependence modifier.
4986 // iterator(iterators-definition)
4987 // where iterators-definition is iterator-specifier [,
4988 // iterators-definition ]
4989 // where iterator-specifier is [ iterator-type ] identifier =
4990 // range-specification
4991 HasIterator = true;
4993 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4994 Data.DepModOrTailExpr = IteratorRes.get();
4995 // Parse ','
4996 ExpectAndConsume(tok::comma);
4997 }
4998 }
4999 // Handle dependency type for depend clause.
5000 ColonProtectionRAIIObject ColonRAII(*this);
5001 Data.ExtraModifier = getOpenMPSimpleClauseType(
5002 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5003 getLangOpts());
5004 Data.ExtraModifierLoc = Tok.getLocation();
5005 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
5006 (Kind == OMPC_doacross &&
5007 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
5008 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5010 } else {
5011 ConsumeToken();
5012 // Special processing for depend(source) clause.
5013 if (DKind == OMPD_ordered_standalone && Kind == OMPC_depend &&
5014 Data.ExtraModifier == OMPC_DEPEND_source) {
5015 // Parse ')'.
5016 T.consumeClose();
5017 return false;
5018 }
5019 }
5020 if (Tok.is(tok::colon)) {
5021 Data.ColonLoc = ConsumeToken();
5022 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
5023 Diag(Tok, DKind == OMPD_ordered_standalone
5024 ? diag::warn_pragma_expected_colon_r_paren
5025 : diag::warn_pragma_expected_colon)
5026 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
5027 }
5028 if (Kind == OMPC_doacross) {
5029 if (Tok.is(tok::identifier) &&
5030 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
5031 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
5032 ? OMPC_DOACROSS_source_omp_cur_iteration
5033 : OMPC_DOACROSS_sink_omp_cur_iteration;
5034 ConsumeToken();
5035 }
5036 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
5037 if (Tok.isNot(tok::minus)) {
5038 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5039 << getOpenMPClauseName(Kind) << 0 << 0;
5040 SkipUntil(tok::r_paren);
5041 return false;
5042 } else {
5043 ConsumeToken();
5044 SourceLocation Loc = Tok.getLocation();
5045 uint64_t Value = 0;
5046 if (Tok.isNot(tok::numeric_constant) ||
5047 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
5048 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
5049 << getOpenMPClauseName(Kind) << 0 << 0;
5050 SkipUntil(tok::r_paren);
5051 return false;
5052 }
5053 }
5054 }
5055 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
5056 if (Tok.isNot(tok::r_paren)) {
5057 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5058 << getOpenMPClauseName(Kind) << 1 << 1;
5059 SkipUntil(tok::r_paren);
5060 return false;
5061 }
5062 }
5063 // Only the 'sink' case has the expression list.
5064 if (Kind == OMPC_doacross &&
5065 (Data.ExtraModifier == OMPC_DOACROSS_source ||
5066 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
5067 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
5068 // Parse ')'.
5069 T.consumeClose();
5070 return false;
5071 }
5072 }
5073 } else if (Kind == OMPC_linear) {
5074 // Try to parse modifier if any.
5075 Data.ExtraModifier = OMPC_LINEAR_val;
5076 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
5077 Data.ExtraModifier =
5078 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5079 Data.ExtraModifierLoc = ConsumeToken();
5080 LinearT.consumeOpen();
5081 NeedRParenForLinear = true;
5082 if (getLangOpts().OpenMP >= 52)
5083 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
5084 << "linear-modifier(list)" << getOpenMPClauseName(Kind)
5085 << "linear(list: [linear-modifier,] step(step-size))";
5086 }
5087 } else if (Kind == OMPC_lastprivate) {
5088 // Try to parse modifier if any.
5089 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
5090 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
5091 // distribute and taskloop based directives.
5092 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
5093 !isOpenMPTaskLoopDirective(DKind)) &&
5094 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
5095 Data.ExtraModifier =
5096 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5097 Data.ExtraModifierLoc = Tok.getLocation();
5098 ConsumeToken();
5099 assert(Tok.is(tok::colon) && "Expected colon.");
5100 Data.ColonLoc = ConsumeToken();
5101 }
5102 } else if (Kind == OMPC_map) {
5103 // Handle optional iterator map modifier.
5104 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
5105 HasIterator = true;
5107 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
5108 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
5109 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
5110 Data.IteratorExpr = IteratorRes.get();
5111 // Parse ','
5112 ExpectAndConsume(tok::comma);
5113 if (getLangOpts().OpenMP < 52) {
5114 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
5115 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
5116 << getLangOpts().OpenMPExtensions << 0;
5117 InvalidIterator = true;
5118 }
5119 }
5120 // Handle map type for map clause.
5121 ColonProtectionRAIIObject ColonRAII(*this);
5122
5123 // The first identifier may be a list item, a map-type or a
5124 // map-type-modifier. The map-type can also be delete which has the same
5125 // spelling of the C++ delete keyword.
5126 Data.ExtraModifier = OMPC_MAP_unknown;
5127 Data.ExtraModifierLoc = Tok.getLocation();
5128
5129 // Check for presence of a colon in the map clause.
5130 TentativeParsingAction TPA(*this);
5131 bool ColonPresent = false;
5132 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5133 StopBeforeMatch)) {
5134 if (Tok.is(tok::colon))
5135 ColonPresent = true;
5136 }
5137 TPA.Revert();
5138 // Only parse map-type-modifier[s] and map-type if a colon is present in
5139 // the map clause.
5140 if (ColonPresent) {
5141 if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
5142 Diag(Tok, diag::err_omp_map_modifier_specification_list);
5143 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
5144 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
5145 parseMapType(*this, Data);
5146 else
5147 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
5148 }
5149 if (Data.ExtraModifier == OMPC_MAP_unknown) {
5150 Data.ExtraModifier = OMPC_MAP_tofrom;
5151 if (getLangOpts().OpenMP >= 52) {
5152 if (DKind == OMPD_target_enter_data)
5153 Data.ExtraModifier = OMPC_MAP_to;
5154 else if (DKind == OMPD_target_exit_data)
5155 Data.ExtraModifier = OMPC_MAP_from;
5156 }
5157 Data.IsMapTypeImplicit = true;
5158 }
5159
5160 if (Tok.is(tok::colon))
5161 Data.ColonLoc = ConsumeToken();
5162 } else if (Kind == OMPC_to || Kind == OMPC_from) {
5163 while (Tok.is(tok::identifier)) {
5164 auto Modifier = static_cast<OpenMPMotionModifierKind>(
5165 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5166 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
5167 break;
5168 Data.MotionModifiers.push_back(Modifier);
5169 Data.MotionModifiersLoc.push_back(Tok.getLocation());
5170 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
5171 ExprResult Tail;
5172 Tail = ParseOpenMPIteratorsExpr();
5173 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5174 /*DiscardedValue=*/false);
5175 if (Tail.isUsable())
5176 Data.IteratorExpr = Tail.get();
5177 } else {
5178 ConsumeToken();
5179 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
5180 IsInvalidMapperModifier = parseMapperModifier(Data);
5181 if (IsInvalidMapperModifier)
5182 break;
5183 }
5184 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
5185 if (getLangOpts().OpenMP < 51)
5186 break;
5187 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
5188 // TODO: Is that intentional?
5189 if (Tok.is(tok::comma))
5190 ConsumeToken();
5191 }
5192 }
5193 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
5194 if (!IsInvalidMapperModifier) {
5195 if (getLangOpts().OpenMP < 51)
5196 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
5197 else
5198 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
5199 }
5200 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5202 }
5203 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
5204 // that intentional?
5205 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
5206 Tok.is(tok::colon))
5207 Data.ColonLoc = ConsumeToken();
5208 } else if (Kind == OMPC_allocate ||
5209 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
5210 PP.getSpelling(Tok) == "iterator")) {
5211 // Handle optional allocator and align modifiers followed by colon
5212 // delimiter.
5213 ColonProtectionRAIIObject ColonRAII(*this);
5214 TentativeParsingAction TPA(*this);
5215 // OpenMP 5.0, 2.10.1, task Construct.
5216 // where aff-modifier is one of the following:
5217 // iterator(iterators-definition)
5218 ExprResult Tail;
5219 if (Kind == OMPC_allocate) {
5220 Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
5221 } else {
5222 HasIterator = true;
5224 Tail = ParseOpenMPIteratorsExpr();
5225 }
5226 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5227 /*DiscardedValue=*/false);
5228 if (Tail.isUsable() || Data.AllocateAlignment) {
5229 if (Tok.is(tok::colon)) {
5230 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
5231 Data.ColonLoc = ConsumeToken();
5232 TPA.Commit();
5233 } else {
5234 // Colon not found, parse only list of variables.
5235 TPA.Revert();
5236 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
5237 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5239 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
5240 }
5241 }
5242 } else {
5243 // Parsing was unsuccessfull, revert and skip to the end of clause or
5244 // directive.
5245 TPA.Revert();
5246 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5248 }
5249 } else if (Kind == OMPC_adjust_args) {
5250 // Handle adjust-op for adjust_args clause.
5251 ColonProtectionRAIIObject ColonRAII(*this);
5252 Data.ExtraModifier = getOpenMPSimpleClauseType(
5253 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5254 getLangOpts());
5255 Data.ExtraModifierLoc = Tok.getLocation();
5256 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
5257 Diag(Tok, diag::err_omp_unknown_adjust_args_op)
5258 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
5259 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5260 } else {
5261 ConsumeToken();
5262 if (Tok.is(tok::colon))
5263 Data.ColonLoc = Tok.getLocation();
5264 if (getLangOpts().OpenMP >= 61) {
5265 // Handle the optional fallback argument for the need_device_ptr
5266 // modifier.
5267 if (Tok.is(tok::l_paren)) {
5268 BalancedDelimiterTracker T(*this, tok::l_paren);
5269 T.consumeOpen();
5270 if (Tok.is(tok::identifier)) {
5271 std::string Modifier = PP.getSpelling(Tok);
5272 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
5273 Data.NeedDevicePtrModifier =
5274 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
5275 : OMPC_NEED_DEVICE_PTR_fb_preserve;
5276 } else {
5277 Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);
5278 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5280 return false;
5281 }
5282 ConsumeToken();
5283 if (Tok.is(tok::r_paren)) {
5284 Data.NeedDevicePtrModifierLoc = Tok.getLocation();
5286 } else {
5287 Diag(Tok, diag::err_expected) << tok::r_paren;
5288 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5290 return false;
5291 }
5292 } else {
5293 Data.NeedDevicePtrModifier = OMPC_NEED_DEVICE_PTR_unknown;
5294 }
5295 }
5296 }
5297 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
5298 "adjust-op");
5299 }
5300 } else if (Kind == OMPC_use_device_ptr) {
5301 // Handle optional fallback modifier for use_device_ptr clause.
5302 // use_device_ptr([fb_preserve | fb_nullify :] list)
5304 if (getLangOpts().OpenMP >= 61 && Tok.is(tok::identifier)) {
5305 auto FallbackModifier = static_cast<OpenMPUseDevicePtrFallbackModifier>(
5306 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5307 if (FallbackModifier != OMPC_USE_DEVICE_PTR_FALLBACK_unknown) {
5308 Data.ExtraModifier = FallbackModifier;
5309 Data.ExtraModifierLoc = Tok.getLocation();
5310 ConsumeToken();
5311 if (Tok.is(tok::colon))
5312 Data.ColonLoc = ConsumeToken();
5313 else
5314 Diag(Tok, diag::err_modifier_expected_colon) << "fallback";
5315 }
5316 }
5317 } else if (Kind == OMPC_num_teams || Kind == OMPC_thread_limit) {
5318 int Mod = 0;
5319 // Handle optional dims and lower-bound modifiers for num_teams clause, and
5320 // the optional dims modifier for thread_limit clause.
5321 Data.ExtraModifierArray[0] = Data.ExtraModifierArray[1] =
5322 Kind == OMPC_num_teams ? static_cast<int>(OMPC_NUMTEAMS_unknown)
5323 : static_cast<int>(OMPC_THREADLIMIT_unknown);
5324
5325 // Lower-bound modifier is only accepted in num_teams.
5326 bool CanParseLowerBoundModifier = (Kind == OMPC_num_teams);
5327 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("dims") &&
5328 NextToken().is(tok::l_paren)) {
5329 SourceLocation TLoc = Tok.getLocation();
5330 ConsumeToken();
5331 SourceLocation RLoc;
5332 ExprResult ExprR = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
5333 if (ExprR.isUsable()) {
5334 Data.ExtraModifierArray[Mod] =
5335 Kind == OMPC_num_teams ? static_cast<int>(OMPC_NUMTEAMS_dims)
5336 : static_cast<int>(OMPC_THREADLIMIT_dims);
5337 Data.ExtraModifierExprArray[Mod] = ExprR.get();
5338 Data.ExtraModifierLocArray[Mod] = TLoc;
5339 ++Mod;
5340 }
5341
5342 if (Tok.is(tok::colon)) {
5343 // A colon was found, no more modifiers are expected.
5344 ConsumeToken();
5345 CanParseLowerBoundModifier = false;
5346 } else if (CanParseLowerBoundModifier && Tok.is(tok::comma)) {
5347 // num_teams(dims(N), lower : upper) is invalid. Only lower:upper may
5348 // follow dims via comma, but sema will reject the combination.
5349 ConsumeToken();
5350 } else {
5351 Diag(Tok, diag::err_modifier_expected_colon)
5352 << getOpenMPClauseName(Kind);
5353 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5354 Data.RLoc = Tok.getLocation();
5355 if (!T.consumeClose())
5356 Data.RLoc = T.getCloseLocation();
5357 return true;
5358 }
5359 }
5360
5361 // The lower bound modifier must appear as the last modifier.
5362 if (CanParseLowerBoundModifier) {
5363 TentativeParsingAction TPA(*this);
5364 SourceLocation TLoc = Tok.getLocation();
5366 if (FirstExpr.isInvalid()) {
5367 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5368 Data.RLoc = Tok.getLocation();
5369 if (!T.consumeClose())
5370 Data.RLoc = T.getCloseLocation();
5371 TPA.Commit();
5372 return true;
5373 }
5374
5375 if (Tok.is(tok::colon)) {
5376 // Correctly parsed the lower bound modifier.
5377 ConsumeToken();
5378 Data.ExtraModifierArray[Mod] = OMPC_NUMTEAMS_lower_bound;
5379 Data.ExtraModifierExprArray[Mod] = FirstExpr.get();
5380 Data.ExtraModifierLocArray[Mod] = TLoc;
5381 TPA.Commit();
5382 } else {
5383 // Could not find the colon after the expression, revert it and let this
5384 // function parse it as a list of expressions.
5385 TPA.Revert();
5386 }
5387 }
5388 } else if (Kind == OMPC_num_threads) {
5389 Data.ExtraModifierArray[0] = static_cast<int>(OMPC_NUMTHREADS_unknown);
5390 Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_unknown);
5391
5392 bool HasModifier = false;
5393 while (true) {
5394 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("dims") &&
5395 NextToken().is(tok::l_paren)) {
5396 // Parse the dims modifier.
5397 SourceLocation TLoc = Tok.getLocation();
5398 ConsumeToken();
5399 SourceLocation RLoc;
5400
5401 ExprResult ExprR =
5402 ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
5403
5404 if (Data.ExtraModifierArray[1] != OMPC_NUMTHREADS_unknown)
5405 Diag(TLoc, diag::err_omp_incompatible_modifiers)
5406 << getOpenMPSimpleClauseTypeName(Kind, OMPC_NUMTHREADS_dims)
5407 << getOpenMPSimpleClauseTypeName(Kind, Data.ExtraModifierArray[1])
5408 << getOpenMPClauseName(Kind);
5409
5410 Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_dims);
5411 Data.ExtraModifierExprArray[1] =
5412 (ExprR.isUsable()) ? ExprR.get() : nullptr;
5413 Data.ExtraModifierLocArray[1] = TLoc;
5414 HasModifier = true;
5415 } else {
5416 // Parse any other modifier.
5418 static_cast<OpenMPNumThreadsClauseModifier>(
5420 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5421 getLangOpts()));
5422
5423 if (Modifier != OMPC_NUMTHREADS_unknown) {
5424 if (Data.ExtraModifierArray[0] != OMPC_NUMTHREADS_unknown)
5425 Diag(Tok, diag::err_omp_incompatible_modifiers)
5426 << getOpenMPSimpleClauseTypeName(Kind, Modifier)
5428 Data.ExtraModifierArray[0])
5429 << getOpenMPClauseName(Kind);
5430 Data.ExtraModifierArray[0] = Modifier;
5431 Data.ExtraModifierLocArray[0] = Tok.getLocation();
5433 HasModifier = true;
5434 } else {
5435 // Not a recognized modifier.
5436 break;
5437 }
5438 }
5439
5440 // If a comma is present, continue parsing modifiers, and stop otherwise.
5441 if (Tok.is(tok::comma))
5442 ConsumeToken();
5443 else
5444 break;
5445 }
5446
5447 // If any modifier was parsed, the next token must be a colon.
5448 if (HasModifier) {
5449 if (!Tok.is(tok::colon)) {
5450 Diag(Tok, diag::err_modifier_expected_colon)
5451 << getOpenMPClauseName(Kind);
5452 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5453 Data.RLoc = Tok.getLocation();
5454 if (!T.consumeClose())
5455 Data.RLoc = T.getCloseLocation();
5456 return true;
5457 }
5458 ConsumeToken();
5459 }
5460 }
5461
5462 bool IsComma =
5463 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
5464 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
5465 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
5466 (Kind == OMPC_reduction && !InvalidReductionId) ||
5467 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
5468 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
5469 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
5470 (Kind == OMPC_adjust_args &&
5471 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
5472 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
5473 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
5474 Tok.isNot(tok::annot_pragma_openmp_end))) {
5475 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
5476 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
5478 // Parse variable
5480 if (VarExpr.isUsable()) {
5481 Vars.push_back(VarExpr.get());
5482 } else {
5483 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5485 }
5486 }
5487 // Skip ',' if any
5488 IsComma = Tok.is(tok::comma);
5489 if (IsComma)
5490 ConsumeToken();
5491 else if (Tok.isNot(tok::r_paren) &&
5492 Tok.isNot(tok::annot_pragma_openmp_end) &&
5493 (!MayHaveTail || Tok.isNot(tok::colon))) {
5494 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
5495 Diag(Tok, diag::err_omp_expected_punc)
5496 << ((Kind == OMPC_flush)
5497 ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
5498 : getOpenMPClauseName(Kind))
5499 << (Kind == OMPC_flush);
5500 }
5501 }
5502
5503 // Parse ')' for linear clause with modifier.
5504 if (NeedRParenForLinear)
5505 LinearT.consumeClose();
5506 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
5507 // or parse ':' alignment.
5508 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
5509 bool StepFound = false;
5510 bool ModifierFound = false;
5511 if (MustHaveTail) {
5512 Data.ColonLoc = Tok.getLocation();
5514
5515 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
5516 bool Malformed = false;
5517 while (Tok.isNot(tok::r_paren)) {
5518 if (Tok.is(tok::identifier)) {
5519 // identifier could be a linear kind (val, uval, ref) or step
5520 // modifier or step size
5521 OpenMPLinearClauseKind LinKind =
5523 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5524 getLangOpts()));
5525
5526 if (LinKind == OMPC_LINEAR_step) {
5527 if (StepFound)
5528 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
5529
5530 BalancedDelimiterTracker StepT(*this, tok::l_paren,
5531 tok::annot_pragma_openmp_end);
5532 SourceLocation StepModifierLoc = ConsumeToken();
5533 // parse '('
5534 if (StepT.consumeOpen())
5535 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
5536
5537 // parse step size expression
5538 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5539 if (StepFound)
5540 Data.StepModifierLoc = StepModifierLoc;
5541
5542 // parse ')'
5543 StepT.consumeClose();
5544 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
5545 if (ModifierFound)
5546 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
5547
5548 Data.ExtraModifier = LinKind;
5549 Data.ExtraModifierLoc = ConsumeToken();
5550 ModifierFound = true;
5551 } else {
5552 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5553 if (!StepFound) {
5554 Malformed = true;
5555 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5557 }
5558 }
5559 } else {
5560 // parse an integer expression as step size
5561 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5562 }
5563
5564 if (Tok.is(tok::comma))
5565 ConsumeToken();
5566 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
5567 break;
5568 }
5569 if (!Malformed && !StepFound && !ModifierFound)
5570 Diag(ELoc, diag::err_expected_expression);
5571 } else {
5572 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
5574 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
5575 /*DiscardedValue*/ false);
5576 if (Tail.isUsable())
5577 Data.DepModOrTailExpr = Tail.get();
5578 else
5579 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5581 }
5582 }
5583
5584 // Parse ')'.
5585 Data.RLoc = Tok.getLocation();
5586 if (!T.consumeClose())
5587 Data.RLoc = T.getCloseLocation();
5588 // Exit from scope when the iterator is used in depend clause.
5589 if (HasIterator)
5590 ExitScope();
5591 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5592 Vars.empty()) ||
5593 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5594 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5595}
5596
5597OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5598 OpenMPClauseKind Kind,
5599 bool ParseOnly) {
5600 SourceLocation Loc = Tok.getLocation();
5601 SourceLocation LOpen = ConsumeToken();
5604
5605 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5606 return nullptr;
5607
5608 if (ParseOnly)
5609 return nullptr;
5610 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5611 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5612}
5613
5614bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5615 SourceLocation &ClauseNameLoc,
5616 SourceLocation &OpenLoc,
5617 SourceLocation &CloseLoc,
5619 bool ReqIntConst) {
5620 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5621 "Expected parsing to start at clause name");
5622 ClauseNameLoc = ConsumeToken();
5623
5624 // Parse inside of '(' and ')'.
5625 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5626 if (T.consumeOpen()) {
5627 Diag(Tok, diag::err_expected) << tok::l_paren;
5628 return true;
5629 }
5630
5631 // Parse the list with interleaved commas.
5632 do {
5633 ExprResult Val =
5635 if (!Val.isUsable()) {
5636 // Encountered something other than an expression; abort to ')'.
5637 T.skipToEnd();
5638 return true;
5639 }
5640 Exprs.push_back(Val.get());
5641 } while (TryConsumeToken(tok::comma));
5642
5643 bool Result = T.consumeClose();
5644 OpenLoc = T.getOpenLocation();
5645 CloseLoc = T.getCloseLocation();
5646 return Result;
5647}
Defines the clang::ASTContext interface.
bool is(tok::TokenKind Kind) const
Token Tok
The Token.
bool isNot(T Kind) const
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
static OpenMPDirectiveKind checkOpenMPDirectiveName(Parser &P, SourceLocation Loc, OpenMPDirectiveKind Kind, StringRef Name)
static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P)
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)
static ExprResult parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse 'allocate' clause modifiers.
static DeclarationName parseOpenMPReductionId(Parser &P)
static ExprResult parseContextScore(Parser &P)
Parse optional 'score' '(' <expr> ')' ':'.
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)
Parse step size expression.
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, SmallVectorImpl< Expr * > &Uniforms, SmallVectorImpl< Expr * > &Aligneds, SmallVectorImpl< Expr * > &Alignments, SmallVectorImpl< Expr * > &Linears, SmallVectorImpl< unsigned > &LinModifiers, SmallVectorImpl< Expr * > &Steps)
Parses clauses for 'declare simd' directive.
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This file declares semantic analysis functions specific to AMDGPU.
This file declares facilities that support code completion.
This file declares semantic analysis for OpenMP constructs and clauses.
Defines the clang::TokenKind enum and support functions.
VerifyDiagnosticConsumer::Directive Directive
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
llvm::SmallVector< OMPTraitSet, 2 > Sets
The outermost level of selector sets.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
DeclarationNameTable DeclarationNames
Definition ASTContext.h:850
OMPTraitInfo & getNewOMPTraitInfo()
Return a new OMPTraitInfo object owned by this context.
bool isUnset() const
Definition Ownership.h:168
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
bool isUsable() const
Definition Ownership.h:169
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:76
bool isEmpty() const
No scope specifier.
Definition DeclSpec.h:181
TypeSpecifierType TST
Definition DeclSpec.h:250
static const TST TST_unspecified
Definition DeclSpec.h:251
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition DeclBase.h:1136
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
The name of a declaration.
bool isEmpty() const
Evaluates true when this declaration name is empty.
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:178
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:195
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition Expr.h:242
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:224
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition Diagnostic.h:140
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
llvm::omp::Version getOpenMPVersion() const
Return the OpenMP version.
This represents a decl that may have a name.
Definition Decl.h:275
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition Decl.cpp:1976
This is a basic class for representing single OpenMP clause.
static const ParsedAttributesView & none()
Definition ParsedAttr.h:830
ParsedAttributes - A collection of parsed attributes.
Definition ParsedAttr.h:950
Introduces zero or more scopes for parsing.
Definition Parser.h:528
void Enter(unsigned ScopeFlags)
Definition Parser.h:536
ParseScope - Introduces a new scope for parsing.
Definition Parser.h:492
Parser - This implements a parser for the C family of languages.
Definition Parser.h:256
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data)
Parses clauses with list.
TypeResult ParseTypeName(SourceRange *Range=nullptr, DeclaratorContext Context=DeclaratorContext::TypeName, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)
ParseTypeName.
Definition ParseDecl.cpp:45
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Definition Parser.cpp:101
Preprocessor & getPreprocessor() const
Definition Parser.h:291
bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type-modifiers in map clause.
ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral=false)
ParseStringLiteralExpression - This handles the various token types that form string literals,...
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Definition Parser.h:347
Sema & getActions() const
Definition Parser.h:292
void EnterScope(unsigned ScopeFlags)
EnterScope - Start a new scope.
Definition Parser.cpp:440
bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
friend class ParsingOpenMPDirectiveRAII
Definition Parser.h:6405
bool ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
friend class ColonProtectionRAIIObject
Definition Parser.h:281
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
Definition Parser.h:375
ExprResult ParseConstantExpression()
bool TryConsumeToken(tok::TokenKind Expected)
Definition Parser.h:355
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition Parser.h:304
Scope * getCurScope() const
Definition Parser.h:296
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
Definition Parser.h:591
const Token & getCurToken() const
Definition Parser.h:295
void ExitScope()
ExitScope - Pop a scope off the scope stack.
Definition Parser.cpp:450
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
const LangOptions & getLangOpts() const
Definition Parser.h:289
friend class ParenBraceBracketBalancer
Definition Parser.h:283
ExprResult ParseExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Simple precedence-based parser for binary/ternary operators.
Definition ParseExpr.cpp:47
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
Definition Parser.h:572
bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)
Parses a reserved locator like 'omp_all_memory'.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
Definition Parser.h:409
ExprResult ParseAssignmentExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Parse an expr that doesn't include (top-level) commas.
Definition ParseExpr.cpp:75
friend class BalancedDelimiterTracker
Definition Parser.h:284
unsigned ReenterTemplateScopes(MultiParseScope &S, Decl *D)
Re-enter a possible template scope, creating as many template parameter scopes as necessary.
bool ParseOpenMPDeclareBeginVariantDirective(SourceLocation Loc)
Parses 'omp begin declare variant' directive.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
Represents a struct/union/class.
Definition Decl.h:4460
@ OpenMPDirectiveScope
This is the scope of OpenMP executable directive.
Definition Scope.h:111
@ CompoundStmtScope
This is a compound statement scope.
Definition Scope.h:134
@ OpenMPSimdDirectiveScope
This is the scope of some OpenMP simd directive.
Definition Scope.h:119
@ FnScope
This indicates that the scope corresponds to a function, which means that labels are set here.
Definition Scope.h:51
@ OpenMPLoopDirectiveScope
This is the scope of some OpenMP loop directive.
Definition Scope.h:114
@ DeclScope
This is a scope that can contain a declaration.
Definition Scope.h:63
Smart pointer class that efficiently represents Objective-C method names.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8497
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:863
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1137
SemaOpenMP & OpenMP()
Definition Sema.h:1531
void ActOnExitFunctionContext()
void ActOnReenterFunctionContext(Scope *S, Decl *D)
Push the parameters of D, which must be a function, into scope.
ASTContext & getASTContext() const
Definition Sema.h:935
const LangOptions & getLangOpts() const
Definition Sema.h:928
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6749
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8710
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1819
Token - This structure provides full information about a lexed token.
Definition Token.h:36
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition Token.h:142
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition Token.h:104
tok::TokenKind getKind() const
Definition Token.h:99
bool isNot(tok::TokenKind K) const
Definition Token.h:111
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
The base class of the type hierarchy.
Definition TypeBase.h:1879
QualType getCanonicalTypeInternal() const
Definition TypeBase.h:3196
Represents a C++ unqualified-id that has been parsed.
Definition DeclSpec.h:1039
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
Defines the clang::TargetInfo interface.
PRESERVE_NONE bool Ret(InterpState &S)
Definition Interp.h:286
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
Definition TokenKinds.h:101
Top level wrappers for InstallAPI frontend operations.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ CPlusPlus
@ CPlusPlus11
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
@ OMPC_DEFAULTMAP_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_unknown
Stmt Stmt * Callback
Definition StmtOpenMP.h:919
@ OMPC_NEED_DEVICE_PTR_unknown
@ OMPC_ADJUST_ARGS_unknown
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ OMPC_REDUCTION_unknown
OpenMPDeviceType
OpenMP device type for 'device_type' clause.
@ OMPC_DEVICE_TYPE_unknown
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition OpenMPKinds.h:40
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:124
@ AS_none
Definition Specifiers.h:128
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ OMPC_NUMTEAMS_unknown
@ OMPC_DOACROSS_unknown
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_last
StmtResult StmtError()
Definition Ownership.h:266
DeclaratorContext
Definition DeclSpec.h:1902
@ Property
The type of a property.
Definition TypeBase.h:912
@ Result
The result type of a method or function.
Definition TypeBase.h:906
ActionResult< ParsedType > TypeResult
Definition Ownership.h:251
const FunctionProtoType * T
@ OMPC_LASTPRIVATE_unknown
@ OMPC_DEPEND_unknown
Definition OpenMPKinds.h:59
OpenMPGrainsizeClauseModifier
@ OMPC_GRAINSIZE_unknown
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts)
OpenMPNumTasksClauseModifier
@ OMPC_NUMTASKS_unknown
OpenMPUseDevicePtrFallbackModifier
OpenMP 6.1 use_device_ptr fallback modifier.
@ OMPC_USE_DEVICE_PTR_FALLBACK_unknown
ExprResult ExprError()
Definition Ownership.h:265
@ Type
The name was classified as a type.
Definition Sema.h:558
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition OpenMPKinds.h:92
@ OMPC_MOTION_MODIFIER_unknown
Definition OpenMPKinds.h:96
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
@ OMPC_ALLOCATE_unknown
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition OpenMPKinds.h:63
@ OMPC_LINEAR_unknown
Definition OpenMPKinds.h:67
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition OpenMPKinds.h:25
@ OMPC_DYN_GROUPPRIVATE_unknown
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ OMPC_THREADLIMIT_unknown
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
StmtResult StmtEmpty()
Definition Ownership.h:273
SmallVector< Token, 4 > CachedTokens
A set of tokens that has been cached for later parsing.
Definition DeclSpec.h:1256
@ OMPC_DEVICE_unknown
Definition OpenMPKinds.h:51
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition Ownership.h:230
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition OpenMPKinds.h:79
@ OMPC_MAP_MODIFIER_unknown
Definition OpenMPKinds.h:80
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition OpenMPKinds.h:28
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ OMPC_ORDER_unknown
@ OMPC_SCHEDULE_unknown
Definition OpenMPKinds.h:35
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
OpenMPDefaultClauseVariableCategory getOpenMPDefaultVariableCategory(StringRef Str, const LangOptions &LangOpts)
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition OpenMPKinds.h:71
@ OMPC_MAP_unknown
Definition OpenMPKinds.h:75
int const char * function
Definition c++config.h:31
#define false
Definition stdbool.h:26
llvm::omp::TraitProperty Kind
StringRef RawString
The raw string as we parsed it. This is needed for the isa trait set (which accepts anything) and (la...
llvm::omp::TraitSelector Kind
SmallVector< OMPTraitProperty, 1 > Properties
SmallVector< OMPTraitSelector, 2 > Selectors
llvm::omp::TraitSet Kind
Clang specific specialization of the OMPContext to lookup target features.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
llvm::SmallVector< OMPInteropPref, 4 > Prefs
This structure contains most locations needed for by an OMPVarListClause.
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition SemaOpenMP.h:324
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition SemaOpenMP.h:321
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition SemaOpenMP.h:318
SourceLocation Loc
The directive location.
Definition SemaOpenMP.h:327
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition SemaOpenMP.h:315
OMPIteratorExpr::IteratorRange Range
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.