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_depth:
3286 case OMPC_align:
3287 case OMPC_message:
3288 case OMPC_ompx_dyn_cgroup_mem:
3289 case OMPC_dyn_groupprivate:
3290 case OMPC_transparent:
3291 // OpenMP [2.5, Restrictions]
3292 // At most one num_threads clause can appear on the directive.
3293 // OpenMP [2.8.1, simd construct, Restrictions]
3294 // Only one safelen clause can appear on a simd directive.
3295 // Only one simdlen clause can appear on a simd directive.
3296 // Only one collapse clause can appear on a simd directive.
3297 // OpenMP [2.11.1, task Construct, Restrictions]
3298 // At most one if clause can appear on the directive.
3299 // At most one final clause can appear on the directive.
3300 // OpenMP [teams Construct, Restrictions]
3301 // At most one num_teams clause can appear on the directive.
3302 // At most one thread_limit clause can appear on the directive.
3303 // OpenMP [2.9.1, task Construct, Restrictions]
3304 // At most one priority clause can appear on the directive.
3305 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3306 // At most one grainsize clause can appear on the directive.
3307 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3308 // At most one num_tasks clause can appear on the directive.
3309 // OpenMP [2.11.3, allocate Directive, Restrictions]
3310 // At most one allocator clause can appear on the directive.
3311 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3312 // At most one detach clause can appear on the directive.
3313 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3314 // At most one novariants clause can appear on a dispatch directive.
3315 // At most one nocontext clause can appear on a dispatch directive.
3316 // OpenMP [5.1, error directive, Restrictions]
3317 // At most one message clause can appear on the directive
3318 if (!FirstClause) {
3319 Diag(Tok, diag::err_omp_more_one_clause)
3320 << getOpenMPDirectiveName(DKind, OMPVersion)
3321 << getOpenMPClauseName(CKind) << 0;
3322 ErrorFound = true;
3323 }
3324
3325 if (CKind == OMPC_transparent && PP.LookAhead(0).isNot(tok::l_paren)) {
3326 SourceLocation Loc = ConsumeToken();
3327 SourceLocation LLoc = Tok.getLocation();
3328 if (!WrongDirective)
3329 Clause = Actions.OpenMP().ActOnOpenMPTransparentClause(nullptr, LLoc,
3330 LLoc, Loc);
3331 break;
3332 }
3333 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3334 PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3335 Clause = ParseOpenMPClause(CKind, WrongDirective);
3336 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
3337 CKind == OMPC_dyn_groupprivate)
3338 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3339 else
3340 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3341 break;
3342 case OMPC_threadset:
3343 case OMPC_fail:
3344 case OMPC_proc_bind:
3345 case OMPC_atomic_default_mem_order:
3346 case OMPC_at:
3347 case OMPC_severity:
3348 case OMPC_bind:
3349 // OpenMP [2.14.3.1, Restrictions]
3350 // Only a single default clause may be specified on a parallel, task or
3351 // teams directive.
3352 // OpenMP [2.5, parallel Construct, Restrictions]
3353 // At most one proc_bind clause can appear on the directive.
3354 // OpenMP [5.0, Requires directive, Restrictions]
3355 // At most one atomic_default_mem_order clause can appear
3356 // on the directive
3357 // OpenMP [5.1, error directive, Restrictions]
3358 // At most one at clause can appear on the directive
3359 // At most one severity clause can appear on the directive
3360 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3361 // At most one bind clause can appear on a loop directive.
3362 if (!FirstClause) {
3363 Diag(Tok, diag::err_omp_more_one_clause)
3364 << getOpenMPDirectiveName(DKind, OMPVersion)
3365 << getOpenMPClauseName(CKind) << 0;
3366 ErrorFound = true;
3367 }
3368
3369 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3370 break;
3371 case OMPC_device:
3372 case OMPC_schedule:
3373 case OMPC_dist_schedule:
3374 case OMPC_defaultmap:
3375 case OMPC_default:
3376 case OMPC_order:
3377 // OpenMP [2.7.1, Restrictions, p. 3]
3378 // Only one schedule clause can appear on a loop directive.
3379 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3380 // At most one defaultmap clause can appear on the directive.
3381 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3382 // At most one device clause can appear on the directive.
3383 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3384 // At most one order clause may appear on a construct.
3385 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3386 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3387 Diag(Tok, diag::err_omp_more_one_clause)
3388 << getOpenMPDirectiveName(DKind, OMPVersion)
3389 << getOpenMPClauseName(CKind) << 0;
3390 ErrorFound = true;
3391 }
3392 [[fallthrough]];
3393 case OMPC_if:
3394 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3395 break;
3396 case OMPC_holds:
3397 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3398 break;
3399 case OMPC_nowait:
3400 case OMPC_untied:
3401 case OMPC_mergeable:
3402 case OMPC_read:
3403 case OMPC_write:
3404 case OMPC_capture:
3405 case OMPC_compare:
3406 case OMPC_seq_cst:
3407 case OMPC_acq_rel:
3408 case OMPC_acquire:
3409 case OMPC_release:
3410 case OMPC_relaxed:
3411 case OMPC_weak:
3412 case OMPC_threads:
3413 case OMPC_simd:
3414 case OMPC_nogroup:
3415 case OMPC_unified_address:
3416 case OMPC_unified_shared_memory:
3417 case OMPC_reverse_offload:
3418 case OMPC_dynamic_allocators:
3419 case OMPC_full:
3420 // OpenMP [2.7.1, Restrictions, p. 9]
3421 // Only one ordered clause can appear on a loop directive.
3422 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3423 // Only one nowait clause can appear on a for directive.
3424 // OpenMP [5.0, Requires directive, Restrictions]
3425 // Each of the requires clauses can appear at most once on the directive.
3426 if (!FirstClause) {
3427 Diag(Tok, diag::err_omp_more_one_clause)
3428 << getOpenMPDirectiveName(DKind, OMPVersion)
3429 << getOpenMPClauseName(CKind) << 0;
3430 ErrorFound = true;
3431 }
3432
3433 if (CKind == OMPC_nowait && PP.LookAhead(/*N=*/0).is(tok::l_paren) &&
3434 getLangOpts().OpenMP >= 60)
3435 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3436 else
3437 Clause = ParseOpenMPClause(CKind, WrongDirective);
3438 break;
3439 case OMPC_self_maps:
3440 // OpenMP [6.0, self_maps clause]
3441 if (getLangOpts().OpenMP < 60) {
3442 Diag(Tok, diag::err_omp_expected_clause)
3443 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
3444 ErrorFound = true;
3445 }
3446 if (!FirstClause) {
3447 Diag(Tok, diag::err_omp_more_one_clause)
3448 << getOpenMPDirectiveName(DKind, OMPVersion)
3449 << getOpenMPClauseName(CKind) << 0;
3450 ErrorFound = true;
3451 }
3452 Clause = ParseOpenMPClause(CKind, WrongDirective);
3453 break;
3454 case OMPC_update:
3455 if (!FirstClause) {
3456 Diag(Tok, diag::err_omp_more_one_clause)
3457 << getOpenMPDirectiveName(DKind, OMPVersion)
3458 << getOpenMPClauseName(CKind) << 0;
3459 ErrorFound = true;
3460 }
3461 Clause = ParseOpenMPClause(CKind, WrongDirective);
3462 break;
3463 case OMPC_update_depend_objects:
3464 if (!FirstClause) {
3465 Diag(Tok, diag::err_omp_more_one_clause)
3466 << getOpenMPDirectiveName(DKind, OMPVersion)
3467 << getOpenMPClauseName(CKind) << 0;
3468 ErrorFound = true;
3469 }
3470
3471 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3472 break;
3473 case OMPC_num_teams:
3474 case OMPC_thread_limit:
3475 case OMPC_num_threads:
3476 if (!FirstClause) {
3477 Diag(Tok, diag::err_omp_more_one_clause)
3478 << getOpenMPDirectiveName(DKind, OMPVersion)
3479 << getOpenMPClauseName(CKind) << 0;
3480 ErrorFound = true;
3481 }
3482 [[fallthrough]];
3483 case OMPC_private:
3484 case OMPC_firstprivate:
3485 case OMPC_lastprivate:
3486 case OMPC_shared:
3487 case OMPC_reduction:
3488 case OMPC_task_reduction:
3489 case OMPC_in_reduction:
3490 case OMPC_linear:
3491 case OMPC_aligned:
3492 case OMPC_copyin:
3493 case OMPC_copyprivate:
3494 case OMPC_flush:
3495 case OMPC_depend:
3496 case OMPC_map:
3497 case OMPC_to:
3498 case OMPC_from:
3499 case OMPC_use_device_ptr:
3500 case OMPC_use_device_addr:
3501 case OMPC_is_device_ptr:
3502 case OMPC_has_device_addr:
3503 case OMPC_allocate:
3504 case OMPC_nontemporal:
3505 case OMPC_inclusive:
3506 case OMPC_exclusive:
3507 case OMPC_affinity:
3508 case OMPC_doacross:
3509 case OMPC_enter:
3510 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered_standalone &&
3511 CKind == OMPC_depend)
3512 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3513 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3514 break;
3515 case OMPC_sizes:
3516 if (!FirstClause) {
3517 Diag(Tok, diag::err_omp_more_one_clause)
3518 << getOpenMPDirectiveName(DKind, OMPVersion)
3519 << getOpenMPClauseName(CKind) << 0;
3520 ErrorFound = true;
3521 }
3522
3523 Clause = ParseOpenMPSizesClause();
3524 break;
3525 case OMPC_permutation:
3526 if (!FirstClause) {
3527 Diag(Tok, diag::err_omp_more_one_clause)
3528 << getOpenMPDirectiveName(DKind, OMPVersion)
3529 << getOpenMPClauseName(CKind) << 0;
3530 ErrorFound = true;
3531 }
3532 Clause = ParseOpenMPPermutationClause();
3533 break;
3534 case OMPC_counts:
3535 if (!FirstClause) {
3536 Diag(Tok, diag::err_omp_more_one_clause)
3537 << getOpenMPDirectiveName(DKind, OMPVersion)
3538 << getOpenMPClauseName(CKind) << 0;
3539 ErrorFound = true;
3540 }
3541 Clause = ParseOpenMPCountsClause();
3542 break;
3543 case OMPC_uses_allocators:
3544 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3545 break;
3546 case OMPC_destroy:
3547 if (DKind != OMPD_interop) {
3548 if (!FirstClause) {
3549 Diag(Tok, diag::err_omp_more_one_clause)
3550 << getOpenMPDirectiveName(DKind, OMPVersion)
3551 << getOpenMPClauseName(CKind) << 0;
3552 ErrorFound = true;
3553 }
3554 Clause = ParseOpenMPClause(CKind, WrongDirective);
3555 break;
3556 }
3557 [[fallthrough]];
3558 case OMPC_init:
3559 case OMPC_use:
3560 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3561 break;
3562 case OMPC_device_type:
3563 case OMPC_unknown:
3564 skipUntilPragmaOpenMPEnd(DKind);
3565 break;
3566 case OMPC_threadprivate:
3567 case OMPC_groupprivate:
3568 case OMPC_uniform:
3569 case OMPC_match:
3570 if (!WrongDirective)
3571 Diag(Tok, diag::err_omp_unexpected_clause)
3572 << getOpenMPClauseName(CKind)
3573 << getOpenMPDirectiveName(DKind, OMPVersion);
3574 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3575 break;
3576 case OMPC_absent:
3577 case OMPC_contains: {
3578 SourceLocation Loc = ConsumeToken();
3579 SourceLocation LLoc = Tok.getLocation();
3580 SourceLocation RLoc;
3581 llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
3582 BalancedDelimiterTracker T(*this, tok::l_paren);
3583 T.consumeOpen();
3584 do {
3585 OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
3586 if (DK == OMPD_unknown) {
3587 skipUntilPragmaOpenMPEnd(OMPD_assume);
3588 Diag(Tok, diag::err_omp_unexpected_clause)
3589 << getOpenMPClauseName(CKind)
3590 << getOpenMPDirectiveName(DKind, OMPVersion);
3591 break;
3592 }
3594 DKVec.push_back(DK);
3595 ConsumeToken();
3596 } else {
3597 Diag(Tok, diag::err_omp_unexpected_clause)
3598 << getOpenMPClauseName(CKind)
3599 << getOpenMPDirectiveName(DKind, OMPVersion);
3600 }
3601 } while (TryConsumeToken(tok::comma));
3602 RLoc = Tok.getLocation();
3603 T.consumeClose();
3604 if (!WrongDirective)
3605 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3606 CKind, DKVec, Loc, LLoc, RLoc);
3607 break;
3608 }
3609 case OMPC_no_openmp:
3610 case OMPC_no_openmp_routines:
3611 case OMPC_no_openmp_constructs:
3612 case OMPC_no_parallelism: {
3613 if (!FirstClause) {
3614 Diag(Tok, diag::err_omp_more_one_clause)
3615 << getOpenMPDirectiveName(DKind, OMPVersion)
3616 << getOpenMPClauseName(CKind) << 0;
3617 ErrorFound = true;
3618 }
3619 SourceLocation Loc = ConsumeToken();
3620 if (!WrongDirective)
3621 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3622 CKind, Loc, Tok.getLocation());
3623 break;
3624 }
3625 case OMPC_ompx_attribute:
3626 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3627 break;
3628 case OMPC_ompx_bare:
3629 if (DKind == llvm::omp::Directive::OMPD_target) {
3630 // Flang splits the combined directives which requires OMPD_target to be
3631 // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
3632 // to explicitly check whether this clause is applied to an `omp target`
3633 // without `teams` and emit an error.
3634 Diag(Tok, diag::err_omp_unexpected_clause)
3635 << getOpenMPClauseName(CKind)
3636 << getOpenMPDirectiveName(DKind, OMPVersion);
3637 ErrorFound = true;
3638 WrongDirective = true;
3639 }
3640 if (WrongDirective)
3641 Diag(Tok, diag::note_ompx_bare_clause)
3642 << getOpenMPClauseName(CKind) << "target teams";
3643 if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3644 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3645 << getOpenMPClauseName(CKind)
3646 << getOpenMPDirectiveName(DKind, OMPVersion);
3647 ErrorFound = true;
3648 }
3649 Clause = ParseOpenMPClause(CKind, WrongDirective);
3650 break;
3651 case OMPC_looprange:
3652 Clause = ParseOpenMPLoopRangeClause();
3653 break;
3654 default:
3655 break;
3656 }
3657 return ErrorFound ? nullptr : Clause;
3658}
3659
3660/// Parses simple expression in parens for single-expression clauses of OpenMP
3661/// constructs.
3662/// \param RLoc Returned location of right paren.
3664 SourceLocation &RLoc,
3665 bool IsAddressOfOperand) {
3666 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3667 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3668 return ExprError();
3669
3670 SourceLocation ELoc = Tok.getLocation();
3671 ExprResult LHS(
3672 ParseCastExpression(CastParseKind::AnyCastExpr, IsAddressOfOperand,
3674 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3675 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3676
3677 // Parse ')'.
3678 RLoc = Tok.getLocation();
3679 if (!T.consumeClose())
3680 RLoc = T.getCloseLocation();
3681
3682 return Val;
3683}
3684
3685OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3686 bool ParseOnly) {
3688 SourceLocation LLoc = Tok.getLocation();
3689 SourceLocation RLoc;
3690
3691 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3692
3693 if (Val.isInvalid())
3694 return nullptr;
3695
3696 if (ParseOnly)
3697 return nullptr;
3698 return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3699 LLoc, RLoc);
3700}
3701
3702bool Parser::ParseOpenMPIndirectClause(
3703 SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3705 SourceLocation RLoc;
3706
3707 if (Tok.isNot(tok::l_paren)) {
3708 if (ParseOnly)
3709 return false;
3710 DTCI.Indirect = nullptr;
3711 return true;
3712 }
3713
3714 ExprResult Val =
3715 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3716 if (Val.isInvalid())
3717 return false;
3718
3719 if (ParseOnly)
3720 return false;
3721
3722 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3723 !Val.get()->isInstantiationDependent() &&
3725 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3726 if (Ret.isInvalid())
3727 return false;
3728 llvm::APSInt Result;
3729 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3731 if (Ret.isInvalid())
3732 return false;
3733 DTCI.Indirect = Val.get();
3734 return true;
3735 }
3736 return false;
3737}
3738
3739ExprResult Parser::ParseOMPInteropFrSelector() {
3740 ConsumeToken(); // 'fr'
3741 BalancedDelimiterTracker FT(*this, tok::l_paren,
3742 tok::annot_pragma_openmp_end);
3743 if (FT.expectAndConsume(diag::err_expected_lparen_after, "fr")) {
3744 SkipUntil(
3745 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3747 return ExprError();
3748 }
3749 SourceLocation Loc = Tok.getLocation();
3750 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3751 ExprResult Arg = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3752 Arg = Actions.ActOnFinishFullExpr(Arg.get(), Loc, /*DiscardedValue=*/false);
3753 FT.consumeClose();
3754 return Arg;
3755}
3756
3757bool Parser::ParseOMPInteropAttrSelector(SmallVectorImpl<Expr *> &Attrs) {
3758 ConsumeToken(); // 'attr'
3759 BalancedDelimiterTracker AT(*this, tok::l_paren,
3760 tok::annot_pragma_openmp_end);
3761 if (AT.expectAndConsume(diag::err_expected_lparen_after, "attr")) {
3762 SkipUntil(
3763 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3765 return true;
3766 }
3767 bool HasError = false;
3768 // attr() requires at least one ext-string-literal argument; an empty list is
3769 // not permitted by the prefer_type grammar.
3770 if (Tok.is(tok::r_paren)) {
3771 Diag(Tok, diag::err_omp_interop_attr_not_string);
3772 HasError = true;
3773 }
3774 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::r_brace) &&
3775 Tok.isNot(tok::annot_pragma_openmp_end)) {
3776 if (Tok.is(tok::string_literal)) {
3778 if (S.isUsable())
3779 Attrs.push_back(S.get());
3780 else
3781 HasError = true;
3782 } else {
3783 HasError = true;
3784 Diag(Tok, diag::err_omp_interop_attr_not_string);
3785 ConsumeToken();
3786 }
3787 if (Tok.is(tok::comma))
3788 ConsumeToken();
3789 }
3790 AT.consumeClose();
3791 return HasError;
3792}
3793
3794bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3795 OpenMPClauseKind Kind) {
3796 const Token &Tok = getCurToken();
3797 bool HasError = false;
3798 bool IsTarget = false;
3799 bool IsTargetSync = false;
3800
3801 while (Tok.is(tok::identifier)) {
3802 // prefer_type is allowed with 'init' and 'append_args' and must be first.
3803 bool PreferTypeAllowed = (Kind == OMPC_init || Kind == OMPC_append_args) &&
3804 InteropInfo.Prefs.empty() && !IsTarget &&
3805 !IsTargetSync;
3806 if (Tok.getIdentifierInfo()->isStr("target")) {
3807 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3808 // Each interop-type may be specified on an action-clause at most
3809 // once.
3810 if (IsTarget)
3811 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3812 IsTarget = true;
3813 ConsumeToken();
3814 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3815 if (IsTargetSync)
3816 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3817 IsTargetSync = true;
3818 ConsumeToken();
3819 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3820 PreferTypeAllowed) {
3821 if (Kind == OMPC_append_args && getLangOpts().OpenMP < 60) {
3822 Diag(Tok, diag::err_omp_append_args_prefer_type_60);
3823 HasError = true;
3824 }
3825 ConsumeToken();
3826 BalancedDelimiterTracker PT(*this, tok::l_paren,
3827 tok::annot_pragma_openmp_end);
3828 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3829 HasError = true;
3830
3831 // prefer_type requires at least one preference-specification.
3832 if (Tok.is(tok::r_paren)) {
3833 Diag(Tok, diag::err_omp_expected_pref_spec);
3834 HasError = true;
3835 }
3836
3837 while (Tok.isNot(tok::r_paren) &&
3838 Tok.isNot(tok::annot_pragma_openmp_end)) {
3839 // OMP 6.0: { fr(...), attr(...) } brace-grouped pref-spec
3840 if (Tok.is(tok::l_brace)) {
3841 // The brace-grouped form was introduced in OpenMP 6.0; earlier
3842 // versions only allow the flat foreign-runtime-id list.
3843 if (getLangOpts().OpenMP < 60) {
3844 Diag(Tok, diag::err_omp_prefer_type_brace_60);
3845 HasError = true;
3846 }
3847 BalancedDelimiterTracker BT(*this, tok::l_brace,
3848 tok::annot_pragma_openmp_end);
3849 BT.consumeOpen();
3850 Expr *FrExpr = nullptr;
3851 SmallVector<Expr *, 2> AttrExprs;
3852 bool SeenFr = false;
3853
3854 // A pref-spec requires at least one 'fr'/'attr' selector; {} is not
3855 // permitted by the grammar.
3856 if (Tok.is(tok::r_brace)) {
3857 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3858 HasError = true;
3859 }
3860
3861 while (Tok.isNot(tok::r_brace) &&
3862 Tok.isNot(tok::annot_pragma_openmp_end)) {
3863 if (Tok.is(tok::identifier) &&
3864 Tok.getIdentifierInfo()->isStr("fr")) {
3865 if (SeenFr) {
3866 Diag(Tok, diag::err_omp_interop_multiple_fr);
3867 HasError = true;
3868 ConsumeToken(); // 'fr'
3869 SkipUntil(
3870 {tok::comma, tok::r_brace, tok::annot_pragma_openmp_end},
3872 continue;
3873 }
3874 SeenFr = true;
3875 ExprResult Fr = ParseOMPInteropFrSelector();
3876 if (Fr.isUsable())
3877 FrExpr = Fr.get();
3878 else
3879 HasError = true;
3880 } else if (Tok.is(tok::identifier) &&
3881 Tok.getIdentifierInfo()->isStr("attr")) {
3882 if (ParseOMPInteropAttrSelector(AttrExprs))
3883 HasError = true;
3884 } else {
3885 // Neither 'fr' nor 'attr' (a non-identifier or some other word).
3886 HasError = true;
3887 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3888 ConsumeToken();
3889 }
3890 if (Tok.is(tok::comma))
3891 ConsumeToken();
3892 }
3893 if (BT.consumeClose())
3894 HasError = true;
3895
3896 if (FrExpr || !AttrExprs.empty())
3897 InteropInfo.Prefs.emplace_back(FrExpr, AttrExprs);
3898 InteropInfo.HasPreferAttrs = true;
3899 } else {
3900 // OMP 5.1: flat foreign-runtime-id (string or int). Stored as a
3901 // pref-spec with Fr=expr and no attr() entries.
3902 SourceLocation Loc = Tok.getLocation();
3903 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3904 ExprResult PTExpr =
3905 ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3906 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3907 /*DiscardedValue=*/false);
3908 if (PTExpr.isUsable()) {
3909 InteropInfo.Prefs.emplace_back(PTExpr.get(),
3910 llvm::SmallVector<Expr *, 2>{});
3911 } else {
3912 HasError = true;
3913 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3915 }
3916 }
3917
3918 if (Tok.is(tok::comma))
3919 ConsumeToken();
3920 }
3921 PT.consumeClose();
3922 } else {
3923 HasError = true;
3924 Diag(Tok, diag::err_omp_expected_interop_type);
3925 ConsumeToken();
3926 }
3927 if (!Tok.is(tok::comma))
3928 break;
3929 ConsumeToken();
3930 }
3931
3932 if (!HasError && !IsTarget && !IsTargetSync) {
3933 Diag(Tok, diag::err_omp_expected_interop_type);
3934 HasError = true;
3935 }
3936
3937 if (Kind == OMPC_init) {
3938 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3939 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3940 if (Tok.is(tok::colon))
3941 ConsumeToken();
3942 }
3943
3944 // As of OpenMP 5.1,there are two interop-types, "target" and
3945 // "targetsync". Either or both are allowed for a single interop.
3946 InteropInfo.IsTarget = IsTarget;
3947 InteropInfo.IsTargetSync = IsTargetSync;
3948
3949 return HasError;
3950}
3951
3952OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3953 bool ParseOnly) {
3954 SourceLocation Loc = ConsumeToken();
3955 // Parse '('.
3956 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3957 if (T.expectAndConsume(diag::err_expected_lparen_after,
3958 getOpenMPClauseName(Kind).data()))
3959 return nullptr;
3960
3961 bool InteropError = false;
3962 OMPInteropInfo InteropInfo;
3963 if (Kind == OMPC_init)
3964 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3965
3966 // Parse the variable.
3967 SourceLocation VarLoc = Tok.getLocation();
3968 ExprResult InteropVarExpr = ParseAssignmentExpression();
3969 if (!InteropVarExpr.isUsable()) {
3970 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3972 }
3973
3974 // Parse ')'.
3975 SourceLocation RLoc = Tok.getLocation();
3976 if (!T.consumeClose())
3977 RLoc = T.getCloseLocation();
3978
3979 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3980 return nullptr;
3981
3982 if (Kind == OMPC_init)
3983 return Actions.OpenMP().ActOnOpenMPInitClause(
3984 InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3985 RLoc);
3986 if (Kind == OMPC_use)
3987 return Actions.OpenMP().ActOnOpenMPUseClause(
3988 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3989
3990 if (Kind == OMPC_destroy)
3991 return Actions.OpenMP().ActOnOpenMPDestroyClause(
3992 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3993
3994 llvm_unreachable("Unexpected interop variable clause.");
3995}
3996
3997OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3998 SourceLocation Loc = ConsumeToken();
3999 // Parse '('.
4000 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4001 if (T.expectAndConsume(diag::err_expected_lparen_after,
4002 getOpenMPClauseName(OMPC_ompx_attribute).data()))
4003 return nullptr;
4004
4005 ParsedAttributes ParsedAttrs(AttrFactory);
4006 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
4007
4008 // Parse ')'.
4009 if (T.consumeClose())
4010 return nullptr;
4011
4012 if (ParseOnly)
4013 return nullptr;
4014
4015 SmallVector<Attr *> Attrs;
4016 for (const ParsedAttr &PA : ParsedAttrs) {
4017 switch (PA.getKind()) {
4018 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
4019 if (!PA.checkExactlyNumArgs(Actions, 2))
4020 continue;
4021 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
4022 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
4023 Attrs.push_back(A);
4024 continue;
4025 case ParsedAttr::AT_AMDGPUWavesPerEU:
4026 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
4027 !PA.checkAtMostNumArgs(Actions, 2))
4028 continue;
4029 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
4030 PA, PA.getArgAsExpr(0),
4031 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
4032 Attrs.push_back(A);
4033 continue;
4034 case ParsedAttr::AT_CUDALaunchBounds:
4035 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
4036 !PA.checkAtMostNumArgs(Actions, 3))
4037 continue;
4038 if (auto *A = Actions.CreateLaunchBoundsAttr(
4039 PA, PA.getArgAsExpr(0),
4040 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
4041 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr,
4042 /*IgnoreArch=*/true))
4043 Attrs.push_back(A);
4044 continue;
4045 default:
4046 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
4047 continue;
4048 };
4049 }
4050
4051 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
4052 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
4053}
4054
4055OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
4056 bool ParseOnly) {
4057 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
4058 if (!Val || ParseOnly)
4059 return nullptr;
4060 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
4061 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
4062 static_cast<DefaultKind>(Val->Type) ==
4063 OMP_DEFAULT_firstprivate)) {
4064 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
4065 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
4066 OMP_DEFAULT_private
4067 ? OMPC_private
4068 : OMPC_firstprivate)
4069 << getOpenMPClauseName(OMPC_default) << "5.1";
4070 return nullptr;
4071 }
4072 return Actions.OpenMP().ActOnOpenMPSimpleClause(
4073 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
4074}
4075
4076OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
4077 SourceLocation Loc = Tok.getLocation();
4079
4080 if (ParseOnly)
4081 return nullptr;
4082 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
4083}
4084
4085OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
4086 OpenMPClauseKind Kind,
4087 bool ParseOnly) {
4088 SourceLocation Loc = ConsumeToken();
4089 SourceLocation DelimLoc;
4090 // Parse '('.
4091 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4092 if (T.expectAndConsume(diag::err_expected_lparen_after,
4093 getOpenMPClauseName(Kind).data()))
4094 return nullptr;
4095
4096 ExprResult Val;
4097 SmallVector<unsigned, 4> Arg;
4098 SmallVector<SourceLocation, 4> KLoc;
4099 if (Kind == OMPC_schedule) {
4100 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
4101 Arg.resize(NumberOfElements);
4102 KLoc.resize(NumberOfElements);
4103 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
4104 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
4105 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
4106 unsigned KindModifier = getOpenMPSimpleClauseType(
4107 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4108 if (KindModifier > OMPC_SCHEDULE_unknown) {
4109 // Parse 'modifier'
4110 Arg[Modifier1] = KindModifier;
4111 KLoc[Modifier1] = Tok.getLocation();
4112 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4113 Tok.isNot(tok::annot_pragma_openmp_end))
4115 if (Tok.is(tok::comma)) {
4116 // Parse ',' 'modifier'
4118 KindModifier = getOpenMPSimpleClauseType(
4119 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4120 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
4121 ? KindModifier
4122 : (unsigned)OMPC_SCHEDULE_unknown;
4123 KLoc[Modifier2] = Tok.getLocation();
4124 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4125 Tok.isNot(tok::annot_pragma_openmp_end))
4127 }
4128 // Parse ':'
4129 if (Tok.is(tok::colon))
4131 else
4132 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
4133 KindModifier = getOpenMPSimpleClauseType(
4134 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4135 }
4136 Arg[ScheduleKind] = KindModifier;
4137 KLoc[ScheduleKind] = Tok.getLocation();
4138 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4139 Tok.isNot(tok::annot_pragma_openmp_end))
4141 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
4142 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
4143 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
4144 Tok.is(tok::comma))
4145 DelimLoc = ConsumeAnyToken();
4146 } else if (Kind == OMPC_dist_schedule) {
4147 Arg.push_back(getOpenMPSimpleClauseType(
4148 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4149 KLoc.push_back(Tok.getLocation());
4150 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4151 Tok.isNot(tok::annot_pragma_openmp_end))
4153 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
4154 DelimLoc = ConsumeAnyToken();
4155 } else if (Kind == OMPC_default) {
4156 // Get a default modifier
4157 unsigned Modifier = getOpenMPSimpleClauseType(
4158 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4159
4160 Arg.push_back(Modifier);
4161 KLoc.push_back(Tok.getLocation());
4162 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4163 Tok.isNot(tok::annot_pragma_openmp_end))
4165 // Parse ':'
4166 if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {
4168 // Get a variable-category attribute for default clause modifier
4169 OpenMPDefaultClauseVariableCategory VariableCategory =
4171 Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4172 Arg.push_back(VariableCategory);
4173 KLoc.push_back(Tok.getLocation());
4174 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4175 Tok.isNot(tok::annot_pragma_openmp_end))
4177 } else {
4178 Arg.push_back(OMPC_DEFAULT_VC_all);
4179 KLoc.push_back(SourceLocation());
4180 }
4181 } else if (Kind == OMPC_defaultmap) {
4182 // Get a defaultmap modifier
4183 unsigned Modifier = getOpenMPSimpleClauseType(
4184 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4185
4186 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
4187 // pointer
4188 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
4190 Arg.push_back(Modifier);
4191 KLoc.push_back(Tok.getLocation());
4192 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4193 Tok.isNot(tok::annot_pragma_openmp_end))
4195 // Parse ':'
4196 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
4197 if (Tok.is(tok::colon))
4199 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
4200 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
4201 // Get a defaultmap kind
4202 Arg.push_back(getOpenMPSimpleClauseType(
4203 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4204 KLoc.push_back(Tok.getLocation());
4205 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4206 Tok.isNot(tok::annot_pragma_openmp_end))
4208 } else {
4209 Arg.push_back(OMPC_DEFAULTMAP_unknown);
4210 KLoc.push_back(SourceLocation());
4211 }
4212 } else if (Kind == OMPC_order) {
4213 enum { Modifier, OrderKind, NumberOfElements };
4214 Arg.resize(NumberOfElements);
4215 KLoc.resize(NumberOfElements);
4216 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
4217 Arg[OrderKind] = OMPC_ORDER_unknown;
4218 unsigned KindModifier = getOpenMPSimpleClauseType(
4219 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4220 if (KindModifier > OMPC_ORDER_unknown) {
4221 // Parse 'modifier'
4222 Arg[Modifier] = KindModifier;
4223 KLoc[Modifier] = Tok.getLocation();
4224 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4225 Tok.isNot(tok::annot_pragma_openmp_end))
4227 // Parse ':'
4228 if (Tok.is(tok::colon))
4230 else
4231 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
4232 KindModifier = getOpenMPSimpleClauseType(
4233 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4234 }
4235 Arg[OrderKind] = KindModifier;
4236 KLoc[OrderKind] = Tok.getLocation();
4237 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4238 Tok.isNot(tok::annot_pragma_openmp_end))
4240 } else if (Kind == OMPC_device) {
4241 // Only target executable directives support extended device construct.
4242 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4243 NextToken().is(tok::colon)) {
4244 // Parse optional <device modifier> ':'
4245 Arg.push_back(getOpenMPSimpleClauseType(
4246 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4247 KLoc.push_back(Tok.getLocation());
4249 // Parse ':'
4251 } else {
4252 Arg.push_back(OMPC_DEVICE_unknown);
4253 KLoc.emplace_back();
4254 }
4255 } else if (Kind == OMPC_grainsize) {
4256 // Parse optional <grainsize modifier> ':'
4259 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4260 getLangOpts()));
4261 if (getLangOpts().OpenMP >= 51) {
4262 if (NextToken().is(tok::colon)) {
4263 Arg.push_back(Modifier);
4264 KLoc.push_back(Tok.getLocation());
4265 // Parse modifier
4267 // Parse ':'
4269 } else {
4270 if (Modifier == OMPC_GRAINSIZE_strict) {
4271 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4272 // Parse modifier
4274 }
4275 Arg.push_back(OMPC_GRAINSIZE_unknown);
4276 KLoc.emplace_back();
4277 }
4278 } else {
4279 Arg.push_back(OMPC_GRAINSIZE_unknown);
4280 KLoc.emplace_back();
4281 }
4282 } else if (Kind == OMPC_dyn_groupprivate) {
4283 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
4284 Arg.resize(NumberOfModifiers);
4285 KLoc.resize(NumberOfModifiers);
4286 Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
4287 Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
4288
4289 auto ConsumeModifier = [&]() {
4290 unsigned Type = NumberOfModifiers;
4291 unsigned Modifier;
4292 SourceLocation Loc;
4293 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
4294 NextToken().is(tok::l_paren)) {
4295 ConsumeToken();
4296 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4297 ParenT.consumeOpen();
4298
4299 Modifier = getOpenMPSimpleClauseType(
4300 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4303 Diag(Tok.getLocation(), diag::err_expected)
4304 << "'abort', 'null' or 'default_mem' in fallback modifier";
4305 SkipUntil(tok::r_paren);
4306 return std::make_tuple(Type, Modifier, Loc);
4307 }
4308 Type = ComplexModifier;
4309 Loc = Tok.getLocation();
4310 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4311 Tok.isNot(tok::annot_pragma_openmp_end))
4313 ParenT.consumeClose();
4314 } else {
4315 Modifier = getOpenMPSimpleClauseType(
4316 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4317 if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
4318 Type = SimpleModifier;
4319 Loc = Tok.getLocation();
4320 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4321 Tok.isNot(tok::annot_pragma_openmp_end))
4323 }
4324 }
4325 return std::make_tuple(Type, Modifier, Loc);
4326 };
4327
4328 auto SaveModifier = [&](unsigned Type, unsigned Modifier,
4329 SourceLocation Loc) {
4330 assert(Type < NumberOfModifiers && "Unexpected modifier type");
4331 if (!KLoc[Type].isValid()) {
4332 Arg[Type] = Modifier;
4333 KLoc[Type] = Loc;
4334 } else {
4335 Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
4336 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
4337 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
4338 }
4339 };
4340
4341 // Parse 'modifier'
4342 auto [Type1, Mod1, Loc1] = ConsumeModifier();
4343 if (Type1 < NumberOfModifiers) {
4344 SaveModifier(Type1, Mod1, Loc1);
4345 if (Tok.is(tok::comma)) {
4346 // Parse ',' 'modifier'
4348 auto [Type2, Mod2, Loc2] = ConsumeModifier();
4349 if (Type2 < NumberOfModifiers)
4350 SaveModifier(Type2, Mod2, Loc2);
4351 }
4352 // Parse ':'
4353 if (Tok.is(tok::colon))
4355 else
4356 Diag(Tok, diag::warn_pragma_expected_colon)
4357 << "dyn_groupprivate modifier";
4358 }
4359 } else if (Kind == OMPC_num_tasks) {
4360 // Parse optional <num_tasks modifier> ':'
4363 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4364 getLangOpts()));
4365 if (getLangOpts().OpenMP >= 51) {
4366 if (NextToken().is(tok::colon)) {
4367 Arg.push_back(Modifier);
4368 KLoc.push_back(Tok.getLocation());
4369 // Parse modifier
4371 // Parse ':'
4373 } else {
4374 if (Modifier == OMPC_NUMTASKS_strict) {
4375 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4376 // Parse modifier
4378 }
4379 Arg.push_back(OMPC_NUMTASKS_unknown);
4380 KLoc.emplace_back();
4381 }
4382 } else {
4383 Arg.push_back(OMPC_NUMTASKS_unknown);
4384 KLoc.emplace_back();
4385 }
4386 } else {
4387 assert(Kind == OMPC_if);
4388 KLoc.push_back(Tok.getLocation());
4389 TentativeParsingAction TPA(*this);
4390 auto DK = parseOpenMPDirectiveKind(*this);
4391 Arg.push_back(static_cast<unsigned>(DK));
4392 if (DK != OMPD_unknown) {
4393 ConsumeToken();
4394 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4395 TPA.Commit();
4396 DelimLoc = ConsumeToken();
4397 } else {
4398 TPA.Revert();
4399 Arg.back() = unsigned(OMPD_unknown);
4400 }
4401 } else {
4402 TPA.Revert();
4403 }
4404 }
4405
4406 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4407 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
4408 Kind == OMPC_if || Kind == OMPC_device ||
4409 Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
4410 Kind == OMPC_dyn_groupprivate;
4411 if (NeedAnExpression) {
4412 SourceLocation ELoc = Tok.getLocation();
4413 ExprResult LHS(
4414 ParseCastExpression(CastParseKind::AnyCastExpr, false,
4416 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4417 Val =
4418 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4419 }
4420
4421 // Parse ')'.
4422 SourceLocation RLoc = Tok.getLocation();
4423 if (!T.consumeClose())
4424 RLoc = T.getCloseLocation();
4425
4426 if (NeedAnExpression && Val.isInvalid())
4427 return nullptr;
4428
4429 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
4430 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
4431 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
4432 Diag(KLoc[0], diag::err_omp_invalid_dsa)
4433 << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==
4434 OMP_DEFAULT_private
4435 ? OMPC_private
4436 : OMPC_firstprivate)
4437 << getOpenMPClauseName(OMPC_default) << "5.1";
4438 return nullptr;
4439 }
4440
4441 if (ParseOnly)
4442 return nullptr;
4443 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4444 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4445}
4446
4447static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4448 UnqualifiedId &ReductionId) {
4449 if (ReductionIdScopeSpec.isEmpty()) {
4450 auto OOK = OO_None;
4451 switch (P.getCurToken().getKind()) {
4452 case tok::plus:
4453 OOK = OO_Plus;
4454 break;
4455 case tok::minus:
4456 OOK = OO_Minus;
4457 break;
4458 case tok::star:
4459 OOK = OO_Star;
4460 break;
4461 case tok::amp:
4462 OOK = OO_Amp;
4463 break;
4464 case tok::pipe:
4465 OOK = OO_Pipe;
4466 break;
4467 case tok::caret:
4468 OOK = OO_Caret;
4469 break;
4470 case tok::ampamp:
4471 OOK = OO_AmpAmp;
4472 break;
4473 case tok::pipepipe:
4474 OOK = OO_PipePipe;
4475 break;
4476 default:
4477 break;
4478 }
4479 if (OOK != OO_None) {
4480 SourceLocation OpLoc = P.ConsumeToken();
4481 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4482 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4483 return false;
4484 }
4485 }
4486 return P.ParseUnqualifiedId(
4487 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4488 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4489 /*AllowDestructorName*/ false,
4490 /*AllowConstructorName*/ false,
4491 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4492}
4493
4494/// Checks if the token is a valid map-type-modifier.
4495/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4497 Token Tok = P.getCurToken();
4498 if (!Tok.is(tok::identifier))
4500
4501 Preprocessor &PP = P.getPreprocessor();
4502 OpenMPMapModifierKind TypeModifier =
4504 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4505 return TypeModifier;
4506}
4507
4509 // Parse '('.
4510 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4511 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4512 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4514 return true;
4515 }
4516 // Parse mapper-identifier
4517 if (getLangOpts().CPlusPlus)
4518 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4519 /*ObjectType=*/nullptr,
4520 /*ObjectHasErrors=*/false,
4521 /*EnteringContext=*/false);
4522 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4523 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4524 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4526 return true;
4527 }
4528 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4529 Data.ReductionOrMapperId = DeclarationNameInfo(
4530 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4531 ConsumeToken();
4532 // Parse ')'.
4533 return T.consumeClose();
4534}
4535
4537
4539 bool HasMapType = false;
4540 SourceLocation PreMapLoc = Tok.getLocation();
4541 StringRef PreMapName = "";
4542 while (getCurToken().isNot(tok::colon)) {
4543 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4544 OpenMPMapClauseKind MapKind = isMapType(*this);
4545 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4546 TypeModifier == OMPC_MAP_MODIFIER_close ||
4547 TypeModifier == OMPC_MAP_MODIFIER_present ||
4548 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4549 Data.MapTypeModifiers.push_back(TypeModifier);
4550 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4551 if (PP.LookAhead(0).isNot(tok::comma) &&
4552 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4553 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4554 << "map type modifier";
4555 ConsumeToken();
4556 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4557 Data.MapTypeModifiers.push_back(TypeModifier);
4558 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4559 ConsumeToken();
4561 return true;
4562 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4563 getLangOpts().OpenMP >= 52)
4564 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4565 << "map type modifier";
4566
4567 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4568 if (!HasMapType) {
4569 HasMapType = true;
4570 Data.ExtraModifier = MapKind;
4571 MapKind = OMPC_MAP_unknown;
4572 PreMapLoc = Tok.getLocation();
4573 PreMapName = Tok.getIdentifierInfo()->getName();
4574 } else {
4575 Diag(Tok, diag::err_omp_more_one_map_type);
4576 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4577 << PreMapName;
4578 }
4579 ConsumeToken();
4580 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
4581 Data.MapTypeModifiers.push_back(TypeModifier);
4582 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4583 if (PP.LookAhead(0).isNot(tok::comma) &&
4584 PP.LookAhead(0).isNot(tok::colon))
4585 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4586 << "map type modifier";
4587 if (getLangOpts().OpenMP < 60)
4588 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4589 << (getLangOpts().OpenMP >= 51
4590 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4591 : 0)
4592 << getLangOpts().OpenMPExtensions << 0;
4593 ConsumeToken();
4594 } else {
4595 // For the case of unknown map-type-modifier or a map-type.
4596 // Map-type is followed by a colon; the function returns when it
4597 // encounters a token followed by a colon.
4598 if (Tok.is(tok::comma)) {
4599 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4600 ConsumeToken();
4601 continue;
4602 }
4603 // Potential map-type token as it is followed by a colon.
4604 if (PP.LookAhead(0).is(tok::colon)) {
4605 if (getLangOpts().OpenMP >= 60) {
4606 break;
4607 } else {
4608 return false;
4609 }
4610 }
4611
4612 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4613 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4614 : 0)
4615 << getLangOpts().OpenMPExtensions
4616 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
4617 ConsumeToken();
4618 }
4619 if (getCurToken().is(tok::comma))
4620 ConsumeToken();
4621 }
4622 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4623 if (!Tok.is(tok::colon)) {
4624 Diag(Tok, diag::err_omp_unknown_map_type);
4625 ConsumeToken();
4626 } else {
4627 Data.ExtraModifier = OMPC_MAP_unknown;
4628 }
4629 }
4630 return false;
4631}
4632
4633/// Checks if the token is a valid map-type.
4634/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4636 Token Tok = P.getCurToken();
4637 // The map-type token can be either an identifier or the C++ delete keyword.
4638 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4639 return OMPC_MAP_unknown;
4640 Preprocessor &PP = P.getPreprocessor();
4641 unsigned MapType =
4643 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4644 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4645 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4646 return static_cast<OpenMPMapClauseKind>(MapType);
4647 return OMPC_MAP_unknown;
4648}
4649
4650/// Parse map-type in map clause.
4651/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4652/// where, map-type ::= to | from | tofrom | alloc | release | delete
4654 Token Tok = P.getCurToken();
4655 if (Tok.is(tok::colon)) {
4656 P.Diag(Tok, diag::err_omp_map_type_missing);
4657 return;
4658 }
4659 Data.ExtraModifier = isMapType(P);
4660 if (Data.ExtraModifier == OMPC_MAP_unknown)
4661 P.Diag(Tok, diag::err_omp_unknown_map_type);
4662 P.ConsumeToken();
4663}
4664
4665ExprResult Parser::ParseOpenMPIteratorsExpr() {
4666 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4667 "Expected 'iterator' token.");
4668 SourceLocation IteratorKwLoc = ConsumeToken();
4669
4670 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4671 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4672 return ExprError();
4673
4674 SourceLocation LLoc = T.getOpenLocation();
4675 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4676 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4677 // Check if the type parsing is required.
4678 ParsedType IteratorType;
4679 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4680 // identifier '=' is not found - parse type.
4682 if (TR.isInvalid()) {
4683 T.skipToEnd();
4684 return ExprError();
4685 }
4686 IteratorType = TR.get();
4687 }
4688
4689 // Parse identifier.
4690 IdentifierInfo *II = nullptr;
4691 SourceLocation IdLoc;
4692 if (Tok.is(tok::identifier)) {
4693 II = Tok.getIdentifierInfo();
4694 IdLoc = ConsumeToken();
4695 } else {
4696 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4697 }
4698
4699 // Parse '='.
4700 SourceLocation AssignLoc;
4701 if (Tok.is(tok::equal))
4702 AssignLoc = ConsumeToken();
4703 else
4704 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4705
4706 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4707 ColonProtectionRAIIObject ColonRAII(*this);
4708 // Parse <begin>
4709 SourceLocation Loc = Tok.getLocation();
4710 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4711 ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4712 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4713 /*DiscardedValue=*/false);
4714 // Parse ':'.
4715 SourceLocation ColonLoc;
4716 if (Tok.is(tok::colon))
4717 ColonLoc = ConsumeToken();
4718
4719 // Parse <end>
4720 Loc = Tok.getLocation();
4721 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4722 ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4723 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4724 /*DiscardedValue=*/false);
4725
4726 SourceLocation SecColonLoc;
4727 ExprResult Step;
4728 // Parse optional step.
4729 if (Tok.is(tok::colon)) {
4730 // Parse ':'
4731 SecColonLoc = ConsumeToken();
4732 // Parse <step>
4733 Loc = Tok.getLocation();
4734 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4735 Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4736 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4737 /*DiscardedValue=*/false);
4738 }
4739
4740 // Parse ',' or ')'
4741 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4742 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4743 if (Tok.is(tok::comma))
4744 ConsumeToken();
4745
4746 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4747 D.DeclIdent = II;
4748 D.DeclIdentLoc = IdLoc;
4749 D.Type = IteratorType;
4750 D.AssignLoc = AssignLoc;
4751 D.ColonLoc = ColonLoc;
4752 D.SecColonLoc = SecColonLoc;
4753 D.Range.Begin = Begin.get();
4754 D.Range.End = End.get();
4755 D.Range.Step = Step.get();
4756 }
4757
4758 // Parse ')'.
4759 SourceLocation RLoc = Tok.getLocation();
4760 if (!T.consumeClose())
4761 RLoc = T.getCloseLocation();
4762
4763 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4764 LLoc, RLoc, Data);
4765}
4766
4769 const LangOptions &LangOpts) {
4770 // Currently the only reserved locator is 'omp_all_memory' which is only
4771 // allowed on a depend clause.
4772 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4773 return false;
4774
4775 if (Tok.is(tok::identifier) &&
4776 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4777
4778 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4779 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4780 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4781 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4782 Data.ExtraModifier != OMPC_DEPEND_inout)
4783 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4784 else
4785 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4786 ? OMPC_DEPEND_outallmemory
4787 : OMPC_DEPEND_inoutallmemory;
4788 ConsumeToken();
4789 return true;
4790 }
4791 return false;
4792}
4793
4794/// Parse step size expression. Returns true if parsing is successfull,
4795/// otherwise returns false.
4797 OpenMPClauseKind CKind, SourceLocation ELoc) {
4799 Sema &Actions = P.getActions();
4800 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4801 /*DiscardedValue*/ false);
4802 if (Tail.isUsable()) {
4803 Data.DepModOrTailExpr = Tail.get();
4804 Token CurTok = P.getCurToken();
4805 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4806 P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4807 }
4808 return true;
4809 }
4810 return false;
4811}
4812
4813/// Parse 'allocate' clause modifiers.
4814/// If allocator-modifier exists, return an expression for it. For both
4815/// allocator and align modifiers, set Data fields as appropriate.
4816static ExprResult
4819 const Token &Tok = P.getCurToken();
4820 Preprocessor &PP = P.getPreprocessor();
4821 ExprResult Tail;
4822 ExprResult Val;
4823 SourceLocation RLoc;
4824 bool AllocatorSeen = false;
4825 bool AlignSeen = false;
4826 SourceLocation CurrentModifierLoc = Tok.getLocation();
4827 auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4829
4830 // Modifiers did not exist before 5.1
4831 if (P.getLangOpts().OpenMP < 51)
4832 return P.ParseAssignmentExpression();
4833
4834 // An allocator-simple-modifier is exclusive and must appear alone. See
4835 // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
4836 // description of "exclusive" property. If we don't recognized an explicit
4837 // simple-/complex- modifier, assume we're looking at expression
4838 // representing allocator and consider ourselves done.
4839 if (CurrentModifier == OMPC_ALLOCATE_unknown)
4840 return P.ParseAssignmentExpression();
4841
4842 do {
4843 P.ConsumeToken();
4844 if (Tok.is(tok::l_paren)) {
4845 switch (CurrentModifier) {
4846 case OMPC_ALLOCATE_allocator: {
4847 if (AllocatorSeen) {
4848 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4849 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4850 << getOpenMPClauseName(Kind);
4851 } else {
4852 Data.AllocClauseModifiers.push_back(CurrentModifier);
4853 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4854 }
4855 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
4856 tok::annot_pragma_openmp_end);
4857 AllocateT.consumeOpen();
4858 Tail = P.ParseAssignmentExpression();
4859 AllocateT.consumeClose();
4860 AllocatorSeen = true;
4861 break;
4862 }
4863 case OMPC_ALLOCATE_align: {
4864 if (AlignSeen) {
4865 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4866 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4867 << getOpenMPClauseName(Kind);
4868 } else {
4869 Data.AllocClauseModifiers.push_back(CurrentModifier);
4870 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4871 }
4872 Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
4873 if (Val.isUsable())
4874 Data.AllocateAlignment = Val.get();
4875 AlignSeen = true;
4876 break;
4877 }
4878 default:
4879 llvm_unreachable("Unexpected allocate modifier");
4880 }
4881 } else {
4882 P.Diag(Tok, diag::err_expected) << tok::l_paren;
4883 }
4884 if (Tok.isNot(tok::comma))
4885 break;
4886 P.ConsumeToken();
4887 CurrentModifierLoc = Tok.getLocation();
4888 CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4890 // A modifier followed by a comma implies another modifier.
4891 if (CurrentModifier == OMPC_ALLOCATE_unknown) {
4892 P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
4893 break;
4894 }
4895 } while (!AllocatorSeen || !AlignSeen);
4896 return Tail;
4897}
4898
4900 OpenMPClauseKind Kind,
4903 UnqualifiedId UnqualifiedReductionId;
4904 bool InvalidReductionId = false;
4905 bool IsInvalidMapperModifier = false;
4906
4907 // Parse '('.
4908 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4909 if (T.expectAndConsume(diag::err_expected_lparen_after,
4910 getOpenMPClauseName(Kind).data()))
4911 return true;
4912
4913 bool HasIterator = false;
4914 bool InvalidIterator = false;
4915 bool NeedRParenForLinear = false;
4916 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4917 tok::annot_pragma_openmp_end);
4918 // Handle reduction-identifier for reduction clause.
4919 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4920 Kind == OMPC_in_reduction) {
4921 Data.ExtraModifier = OMPC_REDUCTION_unknown;
4922 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4923 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4924 NextToken().is(tok::comma)) {
4925 // Parse optional reduction modifier.
4926 Data.ExtraModifier =
4927 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4928 Data.ExtraModifierLoc = Tok.getLocation();
4929 ConsumeToken();
4930 assert(Tok.is(tok::comma) && "Expected comma.");
4931 (void)ConsumeToken();
4932 }
4933 // Handle original(private / shared) Modifier
4934 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
4935 Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
4936 NextToken().is(tok::l_paren)) {
4937 // Parse original(private) modifier.
4938 ConsumeToken();
4939 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4940 ParenT.consumeOpen();
4941 if (Tok.is(tok::kw_private)) {
4942 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
4943 Data.OriginalSharingModifierLoc = Tok.getLocation();
4944 ConsumeToken();
4945 } else if (Tok.is(tok::identifier) &&
4946 (PP.getSpelling(Tok) == "shared" ||
4947 PP.getSpelling(Tok) == "default")) {
4948 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
4949 Data.OriginalSharingModifierLoc = Tok.getLocation();
4950 ConsumeToken();
4951 } else {
4952 Diag(Tok.getLocation(), diag::err_expected)
4953 << "'private or shared or default'";
4954 SkipUntil(tok::r_paren);
4955 return false;
4956 }
4957 ParenT.consumeClose();
4958 if (!Tok.is(tok::comma)) {
4959 Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
4960 return false;
4961 }
4962 (void)ConsumeToken();
4963 }
4964 ColonProtectionRAIIObject ColonRAII(*this);
4965 if (getLangOpts().CPlusPlus)
4966 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4967 /*ObjectType=*/nullptr,
4968 /*ObjectHasErrors=*/false,
4969 /*EnteringContext=*/false);
4970 InvalidReductionId = ParseReductionId(
4971 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4972 if (InvalidReductionId) {
4973 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4975 }
4976 if (Tok.is(tok::colon))
4977 Data.ColonLoc = ConsumeToken();
4978 else
4979 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4980 if (!InvalidReductionId)
4981 Data.ReductionOrMapperId =
4982 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4983 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4984 if (getLangOpts().OpenMP >= 50) {
4985 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4986 // Handle optional dependence modifier.
4987 // iterator(iterators-definition)
4988 // where iterators-definition is iterator-specifier [,
4989 // iterators-definition ]
4990 // where iterator-specifier is [ iterator-type ] identifier =
4991 // range-specification
4992 HasIterator = true;
4994 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4995 Data.DepModOrTailExpr = IteratorRes.get();
4996 // Parse ','
4997 ExpectAndConsume(tok::comma);
4998 }
4999 }
5000 // Handle dependency type for depend clause.
5001 ColonProtectionRAIIObject ColonRAII(*this);
5002 Data.ExtraModifier = getOpenMPSimpleClauseType(
5003 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5004 getLangOpts());
5005 Data.ExtraModifierLoc = Tok.getLocation();
5006 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
5007 (Kind == OMPC_doacross &&
5008 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
5009 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5011 } else {
5012 ConsumeToken();
5013 // Special processing for depend(source) clause.
5014 if (DKind == OMPD_ordered_standalone && Kind == OMPC_depend &&
5015 Data.ExtraModifier == OMPC_DEPEND_source) {
5016 // Parse ')'.
5017 T.consumeClose();
5018 return false;
5019 }
5020 }
5021 if (Tok.is(tok::colon)) {
5022 Data.ColonLoc = ConsumeToken();
5023 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
5024 Diag(Tok, DKind == OMPD_ordered_standalone
5025 ? diag::warn_pragma_expected_colon_r_paren
5026 : diag::warn_pragma_expected_colon)
5027 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
5028 }
5029 if (Kind == OMPC_doacross) {
5030 if (Tok.is(tok::identifier) &&
5031 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
5032 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
5033 ? OMPC_DOACROSS_source_omp_cur_iteration
5034 : OMPC_DOACROSS_sink_omp_cur_iteration;
5035 ConsumeToken();
5036 }
5037 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
5038 if (Tok.isNot(tok::minus)) {
5039 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5040 << getOpenMPClauseName(Kind) << 0 << 0;
5041 SkipUntil(tok::r_paren);
5042 return false;
5043 } else {
5044 ConsumeToken();
5045 SourceLocation Loc = Tok.getLocation();
5046 uint64_t Value = 0;
5047 if (Tok.isNot(tok::numeric_constant) ||
5048 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
5049 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
5050 << getOpenMPClauseName(Kind) << 0 << 0;
5051 SkipUntil(tok::r_paren);
5052 return false;
5053 }
5054 }
5055 }
5056 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
5057 if (Tok.isNot(tok::r_paren)) {
5058 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5059 << getOpenMPClauseName(Kind) << 1 << 1;
5060 SkipUntil(tok::r_paren);
5061 return false;
5062 }
5063 }
5064 // Only the 'sink' case has the expression list.
5065 if (Kind == OMPC_doacross &&
5066 (Data.ExtraModifier == OMPC_DOACROSS_source ||
5067 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
5068 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
5069 // Parse ')'.
5070 T.consumeClose();
5071 return false;
5072 }
5073 }
5074 } else if (Kind == OMPC_linear) {
5075 // Try to parse modifier if any.
5076 Data.ExtraModifier = OMPC_LINEAR_val;
5077 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
5078 Data.ExtraModifier =
5079 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5080 Data.ExtraModifierLoc = ConsumeToken();
5081 LinearT.consumeOpen();
5082 NeedRParenForLinear = true;
5083 if (getLangOpts().OpenMP >= 52)
5084 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
5085 << "linear-modifier(list)" << getOpenMPClauseName(Kind)
5086 << "linear(list: [linear-modifier,] step(step-size))";
5087 }
5088 } else if (Kind == OMPC_lastprivate) {
5089 // Try to parse modifier if any.
5090 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
5091 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
5092 // distribute and taskloop based directives.
5093 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
5094 !isOpenMPTaskLoopDirective(DKind)) &&
5095 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
5096 Data.ExtraModifier =
5097 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5098 Data.ExtraModifierLoc = Tok.getLocation();
5099 ConsumeToken();
5100 assert(Tok.is(tok::colon) && "Expected colon.");
5101 Data.ColonLoc = ConsumeToken();
5102 }
5103 } else if (Kind == OMPC_map) {
5104 // Handle optional iterator map modifier.
5105 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
5106 HasIterator = true;
5108 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
5109 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
5110 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
5111 Data.IteratorExpr = IteratorRes.get();
5112 // Parse ','
5113 ExpectAndConsume(tok::comma);
5114 if (getLangOpts().OpenMP < 52) {
5115 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
5116 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
5117 << getLangOpts().OpenMPExtensions << 0;
5118 InvalidIterator = true;
5119 }
5120 }
5121 // Handle map type for map clause.
5122 ColonProtectionRAIIObject ColonRAII(*this);
5123
5124 // The first identifier may be a list item, a map-type or a
5125 // map-type-modifier. The map-type can also be delete which has the same
5126 // spelling of the C++ delete keyword.
5127 Data.ExtraModifier = OMPC_MAP_unknown;
5128 Data.ExtraModifierLoc = Tok.getLocation();
5129
5130 // Check for presence of a colon in the map clause.
5131 TentativeParsingAction TPA(*this);
5132 bool ColonPresent = false;
5133 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5134 StopBeforeMatch)) {
5135 if (Tok.is(tok::colon))
5136 ColonPresent = true;
5137 }
5138 TPA.Revert();
5139 // Only parse map-type-modifier[s] and map-type if a colon is present in
5140 // the map clause.
5141 if (ColonPresent) {
5142 if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
5143 Diag(Tok, diag::err_omp_map_modifier_specification_list);
5144 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
5145 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
5146 parseMapType(*this, Data);
5147 else
5148 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
5149 }
5150 if (Data.ExtraModifier == OMPC_MAP_unknown) {
5151 Data.ExtraModifier = OMPC_MAP_tofrom;
5152 if (getLangOpts().OpenMP >= 52) {
5153 if (DKind == OMPD_target_enter_data)
5154 Data.ExtraModifier = OMPC_MAP_to;
5155 else if (DKind == OMPD_target_exit_data)
5156 Data.ExtraModifier = OMPC_MAP_from;
5157 }
5158 Data.IsMapTypeImplicit = true;
5159 }
5160
5161 if (Tok.is(tok::colon))
5162 Data.ColonLoc = ConsumeToken();
5163 } else if (Kind == OMPC_to || Kind == OMPC_from) {
5164 while (Tok.is(tok::identifier)) {
5165 auto Modifier = static_cast<OpenMPMotionModifierKind>(
5166 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5167 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
5168 break;
5169 Data.MotionModifiers.push_back(Modifier);
5170 Data.MotionModifiersLoc.push_back(Tok.getLocation());
5171 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
5172 ExprResult Tail;
5173 Tail = ParseOpenMPIteratorsExpr();
5174 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5175 /*DiscardedValue=*/false);
5176 if (Tail.isUsable())
5177 Data.IteratorExpr = Tail.get();
5178 } else {
5179 ConsumeToken();
5180 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
5181 IsInvalidMapperModifier = parseMapperModifier(Data);
5182 if (IsInvalidMapperModifier)
5183 break;
5184 }
5185 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
5186 if (getLangOpts().OpenMP < 51)
5187 break;
5188 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
5189 // TODO: Is that intentional?
5190 if (Tok.is(tok::comma))
5191 ConsumeToken();
5192 }
5193 }
5194 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
5195 if (!IsInvalidMapperModifier) {
5196 if (getLangOpts().OpenMP < 51)
5197 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
5198 else
5199 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
5200 }
5201 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5203 }
5204 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
5205 // that intentional?
5206 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
5207 Tok.is(tok::colon))
5208 Data.ColonLoc = ConsumeToken();
5209 } else if (Kind == OMPC_allocate ||
5210 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
5211 PP.getSpelling(Tok) == "iterator")) {
5212 // Handle optional allocator and align modifiers followed by colon
5213 // delimiter.
5214 ColonProtectionRAIIObject ColonRAII(*this);
5215 TentativeParsingAction TPA(*this);
5216 // OpenMP 5.0, 2.10.1, task Construct.
5217 // where aff-modifier is one of the following:
5218 // iterator(iterators-definition)
5219 ExprResult Tail;
5220 if (Kind == OMPC_allocate) {
5221 Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
5222 } else {
5223 HasIterator = true;
5225 Tail = ParseOpenMPIteratorsExpr();
5226 }
5227 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5228 /*DiscardedValue=*/false);
5229 if (Tail.isUsable() || Data.AllocateAlignment) {
5230 if (Tok.is(tok::colon)) {
5231 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
5232 Data.ColonLoc = ConsumeToken();
5233 TPA.Commit();
5234 } else {
5235 // Colon not found, parse only list of variables.
5236 TPA.Revert();
5237 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
5238 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5240 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
5241 }
5242 }
5243 } else {
5244 // Parsing was unsuccessfull, revert and skip to the end of clause or
5245 // directive.
5246 TPA.Revert();
5247 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5249 }
5250 } else if (Kind == OMPC_adjust_args) {
5251 // Handle adjust-op for adjust_args clause.
5252 ColonProtectionRAIIObject ColonRAII(*this);
5253 Data.ExtraModifier = getOpenMPSimpleClauseType(
5254 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5255 getLangOpts());
5256 Data.ExtraModifierLoc = Tok.getLocation();
5257 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
5258 Diag(Tok, diag::err_omp_unknown_adjust_args_op)
5259 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
5260 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5261 } else {
5262 ConsumeToken();
5263 if (Tok.is(tok::colon))
5264 Data.ColonLoc = Tok.getLocation();
5265 if (getLangOpts().OpenMP >= 61) {
5266 // Handle the optional fallback argument for the need_device_ptr
5267 // modifier.
5268 if (Tok.is(tok::l_paren)) {
5269 BalancedDelimiterTracker T(*this, tok::l_paren);
5270 T.consumeOpen();
5271 if (Tok.is(tok::identifier)) {
5272 std::string Modifier = PP.getSpelling(Tok);
5273 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
5274 Data.NeedDevicePtrModifier =
5275 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
5276 : OMPC_NEED_DEVICE_PTR_fb_preserve;
5277 } else {
5278 Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);
5279 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5281 return false;
5282 }
5283 ConsumeToken();
5284 if (Tok.is(tok::r_paren)) {
5285 Data.NeedDevicePtrModifierLoc = Tok.getLocation();
5287 } else {
5288 Diag(Tok, diag::err_expected) << tok::r_paren;
5289 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5291 return false;
5292 }
5293 } else {
5294 Data.NeedDevicePtrModifier = OMPC_NEED_DEVICE_PTR_unknown;
5295 }
5296 }
5297 }
5298 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
5299 "adjust-op");
5300 }
5301 } else if (Kind == OMPC_use_device_ptr) {
5302 // Handle optional fallback modifier for use_device_ptr clause.
5303 // use_device_ptr([fb_preserve | fb_nullify :] list)
5305 if (getLangOpts().OpenMP >= 61 && Tok.is(tok::identifier)) {
5306 auto FallbackModifier = static_cast<OpenMPUseDevicePtrFallbackModifier>(
5307 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5308 if (FallbackModifier != OMPC_USE_DEVICE_PTR_FALLBACK_unknown) {
5309 Data.ExtraModifier = FallbackModifier;
5310 Data.ExtraModifierLoc = Tok.getLocation();
5311 ConsumeToken();
5312 if (Tok.is(tok::colon))
5313 Data.ColonLoc = ConsumeToken();
5314 else
5315 Diag(Tok, diag::err_modifier_expected_colon) << "fallback";
5316 }
5317 }
5318 } else if (Kind == OMPC_num_teams || Kind == OMPC_thread_limit) {
5319 int Mod = 0;
5320 // Handle optional dims and lower-bound modifiers for num_teams clause, and
5321 // the optional dims modifier for thread_limit clause.
5322 Data.ExtraModifierArray[0] = Data.ExtraModifierArray[1] =
5323 Kind == OMPC_num_teams ? static_cast<int>(OMPC_NUMTEAMS_unknown)
5324 : static_cast<int>(OMPC_THREADLIMIT_unknown);
5325
5326 // Lower-bound modifier is only accepted in num_teams.
5327 bool CanParseLowerBoundModifier = (Kind == OMPC_num_teams);
5328 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("dims") &&
5329 NextToken().is(tok::l_paren)) {
5330 SourceLocation TLoc = Tok.getLocation();
5331 ConsumeToken();
5332 SourceLocation RLoc;
5333 ExprResult ExprR = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
5334 if (ExprR.isUsable()) {
5335 Data.ExtraModifierArray[Mod] =
5336 Kind == OMPC_num_teams ? static_cast<int>(OMPC_NUMTEAMS_dims)
5337 : static_cast<int>(OMPC_THREADLIMIT_dims);
5338 Data.ExtraModifierExprArray[Mod] = ExprR.get();
5339 Data.ExtraModifierLocArray[Mod] = TLoc;
5340 ++Mod;
5341 }
5342
5343 if (Tok.is(tok::colon)) {
5344 // A colon was found, no more modifiers are expected.
5345 ConsumeToken();
5346 CanParseLowerBoundModifier = false;
5347 } else if (CanParseLowerBoundModifier && Tok.is(tok::comma)) {
5348 // num_teams(dims(N), lower : upper) is invalid. Only lower:upper may
5349 // follow dims via comma, but sema will reject the combination.
5350 ConsumeToken();
5351 } else {
5352 Diag(Tok, diag::err_modifier_expected_colon)
5353 << getOpenMPClauseName(Kind);
5354 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5355 Data.RLoc = Tok.getLocation();
5356 if (!T.consumeClose())
5357 Data.RLoc = T.getCloseLocation();
5358 return true;
5359 }
5360 }
5361
5362 // The lower bound modifier must appear as the last modifier.
5363 if (CanParseLowerBoundModifier) {
5364 TentativeParsingAction TPA(*this);
5365 SourceLocation TLoc = Tok.getLocation();
5367 if (FirstExpr.isInvalid()) {
5368 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5369 Data.RLoc = Tok.getLocation();
5370 if (!T.consumeClose())
5371 Data.RLoc = T.getCloseLocation();
5372 TPA.Commit();
5373 return true;
5374 }
5375
5376 if (Tok.is(tok::colon)) {
5377 // Correctly parsed the lower bound modifier.
5378 ConsumeToken();
5379 Data.ExtraModifierArray[Mod] = OMPC_NUMTEAMS_lower_bound;
5380 Data.ExtraModifierExprArray[Mod] = FirstExpr.get();
5381 Data.ExtraModifierLocArray[Mod] = TLoc;
5382 TPA.Commit();
5383 } else {
5384 // Could not find the colon after the expression, revert it and let this
5385 // function parse it as a list of expressions.
5386 TPA.Revert();
5387 }
5388 }
5389 } else if (Kind == OMPC_num_threads) {
5390 Data.ExtraModifierArray[0] = static_cast<int>(OMPC_NUMTHREADS_unknown);
5391 Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_unknown);
5392
5393 bool HasModifier = false;
5394 while (true) {
5395 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("dims") &&
5396 NextToken().is(tok::l_paren)) {
5397 // Parse the dims modifier.
5398 SourceLocation TLoc = Tok.getLocation();
5399 ConsumeToken();
5400 SourceLocation RLoc;
5401
5402 ExprResult ExprR =
5403 ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
5404
5405 if (Data.ExtraModifierArray[1] != OMPC_NUMTHREADS_unknown)
5406 Diag(TLoc, diag::err_omp_incompatible_modifiers)
5407 << getOpenMPSimpleClauseTypeName(Kind, OMPC_NUMTHREADS_dims)
5408 << getOpenMPSimpleClauseTypeName(Kind, Data.ExtraModifierArray[1])
5409 << getOpenMPClauseName(Kind);
5410
5411 Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_dims);
5412 Data.ExtraModifierExprArray[1] =
5413 (ExprR.isUsable()) ? ExprR.get() : nullptr;
5414 Data.ExtraModifierLocArray[1] = TLoc;
5415 HasModifier = true;
5416 } else {
5417 // Parse any other modifier.
5419 static_cast<OpenMPNumThreadsClauseModifier>(
5421 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5422 getLangOpts()));
5423
5424 if (Modifier != OMPC_NUMTHREADS_unknown) {
5425 if (Data.ExtraModifierArray[0] != OMPC_NUMTHREADS_unknown)
5426 Diag(Tok, diag::err_omp_incompatible_modifiers)
5427 << getOpenMPSimpleClauseTypeName(Kind, Modifier)
5429 Data.ExtraModifierArray[0])
5430 << getOpenMPClauseName(Kind);
5431 Data.ExtraModifierArray[0] = Modifier;
5432 Data.ExtraModifierLocArray[0] = Tok.getLocation();
5434 HasModifier = true;
5435 } else {
5436 // Not a recognized modifier.
5437 break;
5438 }
5439 }
5440
5441 // If a comma is present, continue parsing modifiers, and stop otherwise.
5442 if (Tok.is(tok::comma))
5443 ConsumeToken();
5444 else
5445 break;
5446 }
5447
5448 // If any modifier was parsed, the next token must be a colon.
5449 if (HasModifier) {
5450 if (!Tok.is(tok::colon)) {
5451 Diag(Tok, diag::err_modifier_expected_colon)
5452 << getOpenMPClauseName(Kind);
5453 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5454 Data.RLoc = Tok.getLocation();
5455 if (!T.consumeClose())
5456 Data.RLoc = T.getCloseLocation();
5457 return true;
5458 }
5459 ConsumeToken();
5460 }
5461 }
5462
5463 bool IsComma =
5464 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
5465 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
5466 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
5467 (Kind == OMPC_reduction && !InvalidReductionId) ||
5468 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
5469 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
5470 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
5471 (Kind == OMPC_adjust_args &&
5472 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
5473 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
5474 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
5475 Tok.isNot(tok::annot_pragma_openmp_end))) {
5476 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
5477 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
5479 // Parse variable
5481 if (VarExpr.isUsable()) {
5482 Vars.push_back(VarExpr.get());
5483 } else {
5484 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5486 }
5487 }
5488 // Skip ',' if any
5489 IsComma = Tok.is(tok::comma);
5490 if (IsComma)
5491 ConsumeToken();
5492 else if (Tok.isNot(tok::r_paren) &&
5493 Tok.isNot(tok::annot_pragma_openmp_end) &&
5494 (!MayHaveTail || Tok.isNot(tok::colon))) {
5495 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
5496 Diag(Tok, diag::err_omp_expected_punc)
5497 << ((Kind == OMPC_flush)
5498 ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
5499 : getOpenMPClauseName(Kind))
5500 << (Kind == OMPC_flush);
5501 }
5502 }
5503
5504 // Parse ')' for linear clause with modifier.
5505 if (NeedRParenForLinear)
5506 LinearT.consumeClose();
5507 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
5508 // or parse ':' alignment.
5509 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
5510 bool StepFound = false;
5511 bool ModifierFound = false;
5512 if (MustHaveTail) {
5513 Data.ColonLoc = Tok.getLocation();
5515
5516 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
5517 bool Malformed = false;
5518 while (Tok.isNot(tok::r_paren)) {
5519 if (Tok.is(tok::identifier)) {
5520 // identifier could be a linear kind (val, uval, ref) or step
5521 // modifier or step size
5522 OpenMPLinearClauseKind LinKind =
5524 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5525 getLangOpts()));
5526
5527 if (LinKind == OMPC_LINEAR_step) {
5528 if (StepFound)
5529 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
5530
5531 BalancedDelimiterTracker StepT(*this, tok::l_paren,
5532 tok::annot_pragma_openmp_end);
5533 SourceLocation StepModifierLoc = ConsumeToken();
5534 // parse '('
5535 if (StepT.consumeOpen())
5536 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
5537
5538 // parse step size expression
5539 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5540 if (StepFound)
5541 Data.StepModifierLoc = StepModifierLoc;
5542
5543 // parse ')'
5544 StepT.consumeClose();
5545 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
5546 if (ModifierFound)
5547 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
5548
5549 Data.ExtraModifier = LinKind;
5550 Data.ExtraModifierLoc = ConsumeToken();
5551 ModifierFound = true;
5552 } else {
5553 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5554 if (!StepFound) {
5555 Malformed = true;
5556 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5558 }
5559 }
5560 } else {
5561 // parse an integer expression as step size
5562 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5563 }
5564
5565 if (Tok.is(tok::comma))
5566 ConsumeToken();
5567 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
5568 break;
5569 }
5570 if (!Malformed && !StepFound && !ModifierFound)
5571 Diag(ELoc, diag::err_expected_expression);
5572 } else {
5573 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
5575 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
5576 /*DiscardedValue*/ false);
5577 if (Tail.isUsable())
5578 Data.DepModOrTailExpr = Tail.get();
5579 else
5580 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5582 }
5583 }
5584
5585 // Parse ')'.
5586 Data.RLoc = Tok.getLocation();
5587 if (!T.consumeClose())
5588 Data.RLoc = T.getCloseLocation();
5589 // Exit from scope when the iterator is used in depend clause.
5590 if (HasIterator)
5591 ExitScope();
5592 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5593 Vars.empty()) ||
5594 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5595 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5596}
5597
5598OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5599 OpenMPClauseKind Kind,
5600 bool ParseOnly) {
5601 SourceLocation Loc = Tok.getLocation();
5602 SourceLocation LOpen = ConsumeToken();
5605
5606 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5607 return nullptr;
5608
5609 if (ParseOnly)
5610 return nullptr;
5611 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5612 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5613}
5614
5615bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5616 SourceLocation &ClauseNameLoc,
5617 SourceLocation &OpenLoc,
5618 SourceLocation &CloseLoc,
5620 bool ReqIntConst) {
5621 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5622 "Expected parsing to start at clause name");
5623 ClauseNameLoc = ConsumeToken();
5624
5625 // Parse inside of '(' and ')'.
5626 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5627 if (T.consumeOpen()) {
5628 Diag(Tok, diag::err_expected) << tok::l_paren;
5629 return true;
5630 }
5631
5632 // Parse the list with interleaved commas.
5633 do {
5634 ExprResult Val =
5636 if (!Val.isUsable()) {
5637 // Encountered something other than an expression; abort to ')'.
5638 T.skipToEnd();
5639 return true;
5640 }
5641 Exprs.push_back(Val.get());
5642 } while (TryConsumeToken(tok::comma));
5643
5644 bool Result = T.consumeClose();
5645 OpenLoc = T.getOpenLocation();
5646 CloseLoc = T.getCloseLocation();
5647 return Result;
5648}
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:854
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:539
void Enter(unsigned ScopeFlags)
Definition Parser.h:547
ParseScope - Introduces a new scope for parsing.
Definition Parser.h:503
Parser - This implements a parser for the C family of languages.
Definition Parser.h:266
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:302
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:358
Sema & getActions() const
Definition Parser.h:303
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:6429
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:291
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
Definition Parser.h:386
ExprResult ParseConstantExpression()
bool TryConsumeToken(tok::TokenKind Expected)
Definition Parser.h:366
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition Parser.h:315
Scope * getCurScope() const
Definition Parser.h:307
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:602
const Token & getCurToken() const
Definition Parser.h:306
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:300
friend class ParenBraceBracketBalancer
Definition Parser.h:294
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:583
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:420
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:295
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:8549
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:1165
SemaOpenMP & OpenMP()
Definition Sema.h:1559
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:6801
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8762
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:3200
Represents a C++ unqualified-id that has been parsed.
Definition DeclSpec.h:1042
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:284
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:127
@ AS_none
Definition Specifiers.h:131
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:1905
@ 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
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:1259
@ 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:330
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition SemaOpenMP.h:327
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition SemaOpenMP.h:324
SourceLocation Loc
The directive location.
Definition SemaOpenMP.h:333
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition SemaOpenMP.h:321
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.