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 llvm::omp::Version Version = P.getLangOpts().getOpenMPVersion();
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 (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 SmallVector<OMPAdjustArgsItem> AdjustArgsItems;
716 if (P.ParseOpenMPVarList(OMPD_declare_simd,
717 getOpenMPClauseKind(ClauseName), *Vars, Data,
718 AdjustArgsItems))
719 IsError = true;
720 if (CKind == OMPC_aligned) {
721 Alignments.append(Aligneds.size() - Alignments.size(),
722 Data.DepModOrTailExpr);
723 } else if (CKind == OMPC_linear) {
724 assert(0 <= Data.ExtraModifier &&
725 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
726 "Unexpected linear modifier.");
728 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
729 Data.ExtraModifierLoc))
730 Data.ExtraModifier = OMPC_LINEAR_val;
731 LinModifiers.append(Linears.size() - LinModifiers.size(),
732 Data.ExtraModifier);
733 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
734 }
735 } else
736 // TODO: add parsing of other clauses.
737 break;
738 }
739 // Skip ',' if any.
740 if (Tok.is(tok::comma))
741 P.ConsumeToken();
742 }
743 return IsError;
744}
745
747Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
748 CachedTokens &Toks, SourceLocation Loc) {
749 PP.EnterToken(Tok, /*IsReinject*/ true);
750 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
751 /*IsReinject*/ true);
752 // Consume the previously pushed token.
753 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
754 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
755
756 FNContextRAII FnContext(*this, Ptr);
757 OMPDeclareSimdDeclAttr::BranchStateTy BS =
758 OMPDeclareSimdDeclAttr::BS_Undefined;
759 ExprResult Simdlen;
760 SmallVector<Expr *, 4> Uniforms;
761 SmallVector<Expr *, 4> Aligneds;
762 SmallVector<Expr *, 4> Alignments;
763 SmallVector<Expr *, 4> Linears;
764 SmallVector<unsigned, 4> LinModifiers;
765 SmallVector<Expr *, 4> Steps;
766 bool IsError =
767 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
768 Alignments, Linears, LinModifiers, Steps);
769 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
770 // Skip the last annot_pragma_openmp_end.
771 SourceLocation EndLoc = ConsumeAnnotationToken();
772 if (IsError)
773 return Ptr;
774 return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(
775 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
776 LinModifiers, Steps, SourceRange(Loc, EndLoc));
777}
778
779namespace {
780/// Constant used in the diagnostics to distinguish the levels in an OpenMP
781/// contexts: selector-set={selector(trait, ...), ...}, ....
782enum OMPContextLvl {
783 CONTEXT_SELECTOR_SET_LVL = 0,
784 CONTEXT_SELECTOR_LVL = 1,
785 CONTEXT_TRAIT_LVL = 2,
786};
787
788static StringRef stringLiteralParser(Parser &P) {
790 return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
791}
792
793static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
794 OMPContextLvl Lvl) {
795 if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
797 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
798 (void)P.ConsumeToken();
799 return Name;
800 }
801
803 return stringLiteralParser(P);
804
805 P.Diag(Tok.getLocation(),
806 diag::warn_omp_declare_variant_string_literal_or_identifier)
807 << Lvl;
808 return "";
809}
810
811static bool checkForDuplicates(Parser &P, StringRef Name,
812 SourceLocation NameLoc,
813 llvm::StringMap<SourceLocation> &Seen,
814 OMPContextLvl Lvl) {
815 auto Res = Seen.try_emplace(Name, NameLoc);
816 if (Res.second)
817 return false;
818
819 // Each trait-set-selector-name, trait-selector-name and trait-name can
820 // only be specified once.
821 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
822 << Lvl << Name;
823 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
824 << Lvl << Name;
825 return true;
826}
827} // namespace
828
829void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
830 llvm::omp::TraitSet Set,
831 llvm::omp::TraitSelector Selector,
832 llvm::StringMap<SourceLocation> &Seen) {
833 TIProperty.Kind = TraitProperty::invalid;
834
835 SourceLocation NameLoc = Tok.getLocation();
836 StringRef Name;
837 if (Selector == llvm::omp::TraitSelector::target_device_device_num) {
838 Name = "number";
839 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
840 ExprResult DeviceNumExprResult = ParseExpression();
841 if (DeviceNumExprResult.isUsable()) {
842 Expr *DeviceNumExpr = DeviceNumExprResult.get();
843 Actions.OpenMP().ActOnOpenMPDeviceNum(DeviceNumExpr);
844 }
845 return;
846 }
847 Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
848 if (Name.empty()) {
849 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
850 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
851 return;
852 }
853
854 TIProperty.RawString = Name;
855 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
856 if (TIProperty.Kind != TraitProperty::invalid) {
857 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
858 TIProperty.Kind = TraitProperty::invalid;
859 return;
860 }
861
862 // It follows diagnosis and helping notes.
863 // FIXME: We should move the diagnosis string generation into libFrontend.
864 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
865 << Name << getOpenMPContextTraitSelectorName(Selector)
866 << getOpenMPContextTraitSetName(Set);
867
868 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
869 if (SetForName != TraitSet::invalid) {
870 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
871 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
872 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
873 << Name << "<selector-name>"
874 << "(<property-name>)";
875 return;
876 }
877 TraitSelector SelectorForName =
878 getOpenMPContextTraitSelectorKind(Name, SetForName);
879 if (SelectorForName != TraitSelector::invalid) {
880 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
881 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
882 bool AllowsTraitScore = false;
883 bool RequiresProperty = false;
884 isValidTraitSelectorForTraitSet(
885 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
886 AllowsTraitScore, RequiresProperty);
887 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
888 << getOpenMPContextTraitSetName(
889 getOpenMPContextTraitSetForSelector(SelectorForName))
890 << Name << (RequiresProperty ? "(<property-name>)" : "");
891 return;
892 }
893 for (const auto &PotentialSet :
894 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
895 TraitSet::device, TraitSet::target_device}) {
896 TraitProperty PropertyForName =
897 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
898 if (PropertyForName == TraitProperty::invalid)
899 continue;
900 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
901 << getOpenMPContextTraitSetName(
902 getOpenMPContextTraitSetForProperty(PropertyForName))
903 << getOpenMPContextTraitSelectorName(
904 getOpenMPContextTraitSelectorForProperty(PropertyForName))
905 << ("(" + Name + ")").str();
906 return;
907 }
908 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
909 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
910}
911
913 OMPTraitProperty &TIProperty,
914 OMPTraitSelector &TISelector,
915 llvm::StringMap<SourceLocation> &Seen) {
916 assert(TISelector.Kind ==
917 llvm::omp::TraitSelector::implementation_extension &&
918 "Only for extension properties, e.g., "
919 "`implementation={extension(PROPERTY)}`");
920 if (TIProperty.Kind == TraitProperty::invalid)
921 return false;
922
923 if (TIProperty.Kind ==
924 TraitProperty::implementation_extension_disable_implicit_base)
925 return true;
926
927 if (TIProperty.Kind ==
928 TraitProperty::implementation_extension_allow_templates)
929 return true;
930
931 if (TIProperty.Kind ==
932 TraitProperty::implementation_extension_bind_to_declaration)
933 return true;
934
935 auto IsMatchExtension = [](OMPTraitProperty &TP) {
936 return (TP.Kind ==
937 llvm::omp::TraitProperty::implementation_extension_match_all ||
938 TP.Kind ==
939 llvm::omp::TraitProperty::implementation_extension_match_any ||
940 TP.Kind ==
941 llvm::omp::TraitProperty::implementation_extension_match_none);
942 };
943
944 if (IsMatchExtension(TIProperty)) {
945 for (OMPTraitProperty &SeenProp : TISelector.Properties)
946 if (IsMatchExtension(SeenProp)) {
947 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
948 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
949 SeenProp.Kind, SeenProp.RawString);
950 SourceLocation SeenLoc = Seen[SeenName];
951 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
952 << CONTEXT_TRAIT_LVL << SeenName;
953 return false;
954 }
955 return true;
956 }
957
958 llvm_unreachable("Unknown extension property!");
959}
960
961void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
962 llvm::omp::TraitSet Set,
963 llvm::StringMap<SourceLocation> &Seen) {
964 assert(TISelector.Kind != TraitSelector::user_condition &&
965 "User conditions are special properties not handled here!");
966
967 SourceLocation PropertyLoc = Tok.getLocation();
968 OMPTraitProperty TIProperty;
969 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
970
971 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
972 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
973 TISelector, Seen))
974 TIProperty.Kind = TraitProperty::invalid;
975
976 // If we have an invalid property here we already issued a warning.
977 if (TIProperty.Kind == TraitProperty::invalid) {
978 if (PropertyLoc != Tok.getLocation())
979 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
980 << CONTEXT_TRAIT_LVL;
981 return;
982 }
983
984 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
985 TISelector.Kind, Set)) {
986
987 // If we make it here the property, selector, set, score, condition, ... are
988 // all valid (or have been corrected). Thus we can record the property.
989 TISelector.Properties.push_back(TIProperty);
990 return;
991 }
992
993 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
994 << getOpenMPContextTraitPropertyName(TIProperty.Kind,
995 TIProperty.RawString)
996 << getOpenMPContextTraitSelectorName(TISelector.Kind)
997 << getOpenMPContextTraitSetName(Set);
998 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
999 << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1000 TIProperty.RawString)
1001 << getOpenMPContextTraitSelectorName(
1002 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
1003 << getOpenMPContextTraitSetName(
1004 getOpenMPContextTraitSetForProperty(TIProperty.Kind));
1005 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1006 << CONTEXT_TRAIT_LVL;
1007}
1008
1009void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
1010 llvm::omp::TraitSet Set,
1011 llvm::StringMap<SourceLocation> &Seen) {
1012 TISelector.Kind = TraitSelector::invalid;
1013
1014 SourceLocation NameLoc = Tok.getLocation();
1015 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
1016 if (Name.empty()) {
1017 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1018 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1019 return;
1020 }
1021
1022 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name, Set);
1023 if (TISelector.Kind != TraitSelector::invalid) {
1024 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1025 TISelector.Kind = TraitSelector::invalid;
1026 return;
1027 }
1028
1029 // It follows diagnosis and helping notes.
1030 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1031 << Name << getOpenMPContextTraitSetName(Set);
1032
1033 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1034 if (SetForName != TraitSet::invalid) {
1035 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1036 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1037 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1038 << Name << "<selector-name>"
1039 << "<property-name>";
1040 return;
1041 }
1042 for (const auto &PotentialSet :
1043 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1044 TraitSet::device, TraitSet::target_device}) {
1045 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1046 PotentialSet, TraitSelector::invalid, Name);
1047 if (PropertyForName == TraitProperty::invalid)
1048 continue;
1049 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1050 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1051 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1052 << getOpenMPContextTraitSetName(
1053 getOpenMPContextTraitSetForProperty(PropertyForName))
1054 << getOpenMPContextTraitSelectorName(
1055 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1056 << ("(" + Name + ")").str();
1057 return;
1058 }
1059 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1060 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1061}
1062
1063/// Parse optional 'score' '(' <expr> ')' ':'.
1065 ExprResult ScoreExpr;
1066 llvm::SmallString<16> Buffer;
1067 StringRef SelectorName =
1068 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1069 if (SelectorName != "score")
1070 return ScoreExpr;
1071 (void)P.ConsumeToken();
1072 SourceLocation RLoc;
1073 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
1074 // Parse ':'
1075 if (P.getCurToken().is(tok::colon))
1076 (void)P.ConsumeAnyToken();
1077 else
1078 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
1079 << "':'"
1080 << "score expression";
1081 return ScoreExpr;
1082}
1083
1084void Parser::parseOMPContextSelector(
1085 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
1086 llvm::StringMap<SourceLocation> &SeenSelectors) {
1087 unsigned short OuterPC = ParenCount;
1088
1089 // If anything went wrong we issue an error or warning and then skip the rest
1090 // of the selector. However, commas are ambiguous so we look for the nesting
1091 // of parentheses here as well.
1092 auto FinishSelector = [OuterPC, this]() -> void {
1093 bool Done = false;
1094 while (!Done) {
1095 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1096 tok::annot_pragma_openmp_end},
1098 ;
1099 if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
1100 (void)ConsumeParen();
1101 if (OuterPC <= ParenCount) {
1102 Done = true;
1103 break;
1104 }
1105 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
1106 Done = true;
1107 break;
1108 }
1109 (void)ConsumeAnyToken();
1110 }
1111 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1112 << CONTEXT_SELECTOR_LVL;
1113 };
1114
1115 SourceLocation SelectorLoc = Tok.getLocation();
1116 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1117 if (TISelector.Kind == TraitSelector::invalid)
1118 return FinishSelector();
1119
1120 bool AllowsTraitScore = false;
1121 bool RequiresProperty = false;
1122 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
1123 RequiresProperty)) {
1124 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1125 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1126 << getOpenMPContextTraitSetName(Set);
1127 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1128 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1129 << getOpenMPContextTraitSetName(
1130 getOpenMPContextTraitSetForSelector(TISelector.Kind))
1131 << RequiresProperty;
1132 return FinishSelector();
1133 }
1134
1135 if (!RequiresProperty) {
1136 TISelector.Properties.push_back(
1137 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1138 getOpenMPContextTraitSelectorName(TISelector.Kind)});
1139 return;
1140 }
1141
1142 if (!Tok.is(tok::l_paren)) {
1143 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1144 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1145 << getOpenMPContextTraitSetName(Set);
1146 return FinishSelector();
1147 }
1148
1149 if (TISelector.Kind == TraitSelector::user_condition) {
1150 SourceLocation RLoc;
1151 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
1152 if (!Condition.isUsable())
1153 return FinishSelector();
1154 TISelector.ScoreOrCondition = Condition.get();
1155 TISelector.Properties.push_back(
1156 {TraitProperty::user_condition_unknown, "<condition>"});
1157 return;
1158 }
1159
1160 BalancedDelimiterTracker BDT(*this, tok::l_paren,
1161 tok::annot_pragma_openmp_end);
1162 // Parse '('.
1163 (void)BDT.consumeOpen();
1164
1165 SourceLocation ScoreLoc = Tok.getLocation();
1166 ExprResult Score = parseContextScore(*this);
1167
1168 if (!AllowsTraitScore && !Score.isUnset()) {
1169 if (Score.isUsable()) {
1170 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1171 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1172 << getOpenMPContextTraitSetName(Set) << Score.get();
1173 } else {
1174 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1175 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1176 << getOpenMPContextTraitSetName(Set) << "<invalid>";
1177 }
1178 Score = ExprResult();
1179 }
1180
1181 if (Score.isUsable())
1182 TISelector.ScoreOrCondition = Score.get();
1183
1184 llvm::StringMap<SourceLocation> SeenProperties;
1185 do {
1186 parseOMPContextProperty(TISelector, Set, SeenProperties);
1187 } while (TryConsumeToken(tok::comma));
1188
1189 // Parse ')'.
1190 BDT.consumeClose();
1191}
1192
1193void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
1194 llvm::StringMap<SourceLocation> &Seen) {
1195 TISet.Kind = TraitSet::invalid;
1196
1197 SourceLocation NameLoc = Tok.getLocation();
1198 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
1199 if (Name.empty()) {
1200 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1201 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1202 return;
1203 }
1204
1205 TISet.Kind = getOpenMPContextTraitSetKind(Name);
1206 if (TISet.Kind != TraitSet::invalid) {
1207 if (checkForDuplicates(*this, Name, NameLoc, Seen,
1208 CONTEXT_SELECTOR_SET_LVL))
1209 TISet.Kind = TraitSet::invalid;
1210 return;
1211 }
1212
1213 // It follows diagnosis and helping notes.
1214 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1215
1216 TraitSelector SelectorForName =
1217 getOpenMPContextTraitSelectorKind(Name, TISet.Kind);
1218 if (SelectorForName != TraitSelector::invalid) {
1219 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1220 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1221 bool AllowsTraitScore = false;
1222 bool RequiresProperty = false;
1223 isValidTraitSelectorForTraitSet(
1224 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1225 AllowsTraitScore, RequiresProperty);
1226 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1227 << getOpenMPContextTraitSetName(
1228 getOpenMPContextTraitSetForSelector(SelectorForName))
1229 << Name << (RequiresProperty ? "(<property-name>)" : "");
1230 return;
1231 }
1232 for (const auto &PotentialSet :
1233 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1234 TraitSet::device, TraitSet::target_device}) {
1235 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1236 PotentialSet, TraitSelector::invalid, Name);
1237 if (PropertyForName == TraitProperty::invalid)
1238 continue;
1239 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1240 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1241 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1242 << getOpenMPContextTraitSetName(
1243 getOpenMPContextTraitSetForProperty(PropertyForName))
1244 << getOpenMPContextTraitSelectorName(
1245 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1246 << ("(" + Name + ")").str();
1247 return;
1248 }
1249 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1250 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1251}
1252
1253void Parser::parseOMPContextSelectorSet(
1254 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1255 auto OuterBC = BraceCount;
1256
1257 // If anything went wrong we issue an error or warning and then skip the rest
1258 // of the set. However, commas are ambiguous so we look for the nesting
1259 // of braces here as well.
1260 auto FinishSelectorSet = [this, OuterBC]() -> void {
1261 bool Done = false;
1262 while (!Done) {
1263 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1264 tok::annot_pragma_openmp_end},
1266 ;
1267 if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
1268 (void)ConsumeBrace();
1269 if (OuterBC <= BraceCount) {
1270 Done = true;
1271 break;
1272 }
1273 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
1274 Done = true;
1275 break;
1276 }
1277 (void)ConsumeAnyToken();
1278 }
1279 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1280 << CONTEXT_SELECTOR_SET_LVL;
1281 };
1282
1283 parseOMPTraitSetKind(TISet, SeenSets);
1284 if (TISet.Kind == TraitSet::invalid)
1285 return FinishSelectorSet();
1286
1287 // Parse '='.
1288 if (!TryConsumeToken(tok::equal))
1289 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1290 << "="
1291 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
1292 "\"");
1293
1294 // Parse '{'.
1295 if (Tok.is(tok::l_brace)) {
1296 (void)ConsumeBrace();
1297 } else {
1298 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1299 << "{"
1300 << ("'=' that follows the context set name \"" +
1301 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1302 .str();
1303 }
1304
1305 llvm::StringMap<SourceLocation> SeenSelectors;
1306 do {
1307 OMPTraitSelector TISelector;
1308 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1309 if (TISelector.Kind != TraitSelector::invalid &&
1310 !TISelector.Properties.empty())
1311 TISet.Selectors.push_back(TISelector);
1312 } while (TryConsumeToken(tok::comma));
1313
1314 // Parse '}'.
1315 if (Tok.is(tok::r_brace)) {
1316 (void)ConsumeBrace();
1317 } else {
1318 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1319 << "}"
1320 << ("context selectors for the context set \"" +
1321 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1322 .str();
1323 }
1324}
1325
1326bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1327 llvm::StringMap<SourceLocation> SeenSets;
1328 do {
1329 OMPTraitSet TISet;
1330 parseOMPContextSelectorSet(TISet, SeenSets);
1331 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1332 TI.Sets.push_back(TISet);
1333 } while (TryConsumeToken(tok::comma));
1334
1335 return false;
1336}
1337
1338void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1339 CachedTokens &Toks,
1340 SourceLocation Loc) {
1341 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1342 PP.EnterToken(Tok, /*IsReinject*/ true);
1343 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1344 /*IsReinject*/ true);
1345 // Consume the previously pushed token.
1346 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1347 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1348
1349 FNContextRAII FnContext(*this, Ptr);
1350 // Parse function declaration id.
1351 SourceLocation RLoc;
1352 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1353 // instead of MemberExprs.
1354 ExprResult AssociatedFunction;
1355 {
1356 // Do not mark function as is used to prevent its emission if this is the
1357 // only place where it is used.
1358 EnterExpressionEvaluationContext Unevaluated(
1360 AssociatedFunction = ParseOpenMPParensExpr(
1361 getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion), RLoc,
1362 /*IsAddressOfOperand=*/true);
1363 }
1364 if (!AssociatedFunction.isUsable()) {
1365 if (!Tok.is(tok::annot_pragma_openmp_end))
1366 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1367 ;
1368 // Skip the last annot_pragma_openmp_end.
1369 (void)ConsumeAnnotationToken();
1370 return;
1371 }
1372
1373 OMPTraitInfo *ParentTI =
1374 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
1375 ASTContext &ASTCtx = Actions.getASTContext();
1376 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1377 SmallVector<OMPAdjustArgsDescriptor *, 3> AdjustArgs;
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 SmallVector<OMPAdjustArgsItem, 4> Items;
1408 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
1409 Vars, Data, Items);
1410 if (!IsError) {
1411 for (Expr *E : Vars) {
1412 OMPAdjustArgsItem Item;
1413 Item.E = E;
1414 Items.push_back(Item);
1415 }
1416 OpenMPAdjustArgsOpKind AdjustOp =
1417 static_cast<OpenMPAdjustArgsOpKind>(Data.ExtraModifier);
1418 OpenMPNeedDevicePtrModifier NeedDevicePtrModifier =
1420 if (Data.NeedDevicePtrModifierLoc.isValid())
1421 NeedDevicePtrModifier = static_cast<OpenMPNeedDevicePtrModifier>(
1422 Data.NeedDevicePtrModifier);
1423 OMPAdjustArgsDescriptor *Desc =
1424 Actions.OpenMP().ActOnOpenMPAdjustArgsClause(
1425 AdjustOp, NeedDevicePtrModifier, Items, AdjustArgsLoc);
1426 if (Desc)
1427 AdjustArgs.push_back(Desc);
1428 else
1429 IsError = true;
1430 }
1431 break;
1432 }
1433 case OMPC_append_args:
1434 if (!AppendArgs.empty()) {
1435 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1436 << getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion)
1437 << getOpenMPClauseName(CKind) << 0;
1438 IsError = true;
1439 }
1440 if (!IsError) {
1441 AppendArgsLoc = Tok.getLocation();
1442 ConsumeToken();
1443 IsError = parseOpenMPAppendArgs(AppendArgs);
1444 }
1445 break;
1446 default:
1447 llvm_unreachable("Unexpected clause for declare variant.");
1448 }
1449 }
1450 if (IsError) {
1451 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1452 ;
1453 // Skip the last annot_pragma_openmp_end.
1454 (void)ConsumeAnnotationToken();
1455 return;
1456 }
1457 // Skip ',' if any.
1458 if (Tok.is(tok::comma))
1459 ConsumeToken();
1460 }
1461
1462 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1463 Actions.OpenMP().checkOpenMPDeclareVariantFunction(
1464 Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
1465 SourceRange(Loc, Tok.getLocation()));
1466
1467 if (DeclVarData && !TI.Sets.empty())
1468 Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(
1469 DeclVarData->first, DeclVarData->second, TI, AdjustArgs, AppendArgs,
1470 AdjustArgsLoc, AppendArgsLoc, SourceRange(Loc, Tok.getLocation()));
1471
1472 // Skip the last annot_pragma_openmp_end.
1473 (void)ConsumeAnnotationToken();
1474}
1475
1476bool Parser::parseOpenMPAppendArgs(
1477 SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
1478 bool HasError = false;
1479 // Parse '('.
1480 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1481 if (T.expectAndConsume(diag::err_expected_lparen_after,
1482 getOpenMPClauseName(OMPC_append_args).data()))
1483 return true;
1484
1485 // Parse the list of append-ops, each is;
1486 // interop(interop-type[,interop-type]...)
1487 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
1488 ConsumeToken();
1489 BalancedDelimiterTracker IT(*this, tok::l_paren,
1490 tok::annot_pragma_openmp_end);
1491 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
1492 return true;
1493
1494 OMPInteropInfo InteropInfo;
1495 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1496 HasError = true;
1497 else
1498 InteropInfos.push_back(InteropInfo);
1499
1500 IT.consumeClose();
1501 if (Tok.is(tok::comma))
1502 ConsumeToken();
1503 }
1504 if (!HasError && InteropInfos.empty()) {
1505 HasError = true;
1506 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
1507 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1509 }
1510 HasError = T.consumeClose() || HasError;
1511 return HasError;
1512}
1513
1514bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1515 OMPTraitInfo &TI,
1516 OMPTraitInfo *ParentTI) {
1517 // Parse 'match'.
1518 OpenMPClauseKind CKind = Tok.isAnnotation()
1519 ? OMPC_unknown
1520 : getOpenMPClauseKind(PP.getSpelling(Tok));
1521 if (CKind != OMPC_match) {
1522 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1523 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1524 return true;
1525 }
1526 (void)ConsumeToken();
1527 // Parse '('.
1528 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1529 if (T.expectAndConsume(diag::err_expected_lparen_after,
1530 getOpenMPClauseName(OMPC_match).data()))
1531 return true;
1532
1533 // Parse inner context selectors.
1534 parseOMPContextSelectors(Loc, TI);
1535
1536 // Parse ')'
1537 (void)T.consumeClose();
1538
1539 if (!ParentTI)
1540 return false;
1541
1542 // Merge the parent/outer trait info into the one we just parsed and diagnose
1543 // problems.
1544 // TODO: Keep some source location in the TI to provide better diagnostics.
1545 // TODO: Perform some kind of equivalence check on the condition and score
1546 // expressions.
1547 for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1548 bool MergedSet = false;
1549 for (OMPTraitSet &Set : TI.Sets) {
1550 if (Set.Kind != ParentSet.Kind)
1551 continue;
1552 MergedSet = true;
1553 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1554 bool MergedSelector = false;
1555 for (OMPTraitSelector &Selector : Set.Selectors) {
1556 if (Selector.Kind != ParentSelector.Kind)
1557 continue;
1558 MergedSelector = true;
1559 for (const OMPTraitProperty &ParentProperty :
1560 ParentSelector.Properties) {
1561 bool MergedProperty = false;
1562 for (OMPTraitProperty &Property : Selector.Properties) {
1563 // Ignore "equivalent" properties.
1564 if (Property.Kind != ParentProperty.Kind)
1565 continue;
1566
1567 // If the kind is the same but the raw string not, we don't want
1568 // to skip out on the property.
1569 MergedProperty |= Property.RawString == ParentProperty.RawString;
1570
1571 if (Property.RawString == ParentProperty.RawString &&
1572 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1573 continue;
1574
1575 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1576 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1577 } else if (Selector.ScoreOrCondition !=
1578 ParentSelector.ScoreOrCondition) {
1579 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1580 << getOpenMPContextTraitPropertyName(
1581 ParentProperty.Kind, ParentProperty.RawString)
1582 << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1583 << getOpenMPContextTraitSetName(ParentSet.Kind);
1584 }
1585 }
1586 if (!MergedProperty)
1587 Selector.Properties.push_back(ParentProperty);
1588 }
1589 }
1590 if (!MergedSelector)
1591 Set.Selectors.push_back(ParentSelector);
1592 }
1593 }
1594 if (!MergedSet)
1595 TI.Sets.push_back(ParentSet);
1596 }
1597
1598 return false;
1599}
1600
1601void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
1603 SourceLocation Loc) {
1604 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
1605 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1606 OpenMPClauseKind CKind = Tok.isAnnotation()
1607 ? OMPC_unknown
1608 : getOpenMPClauseKind(PP.getSpelling(Tok));
1609 if (DKind == OMPD_depobj && CKind == OMPC_update)
1610 CKind = OMPC_update_depend_objects;
1611 Actions.OpenMP().StartOpenMPClause(CKind);
1612 OMPClause *Clause =
1613 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
1614 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1616 SeenClauses[unsigned(CKind)] = true;
1617 if (Clause != nullptr)
1618 Clauses.push_back(Clause);
1619 if (Tok.is(tok::annot_pragma_openmp_end)) {
1620 Actions.OpenMP().EndOpenMPClause();
1621 break;
1622 }
1623 // Skip ',' if any.
1624 if (Tok.is(tok::comma))
1625 ConsumeToken();
1626 Actions.OpenMP().EndOpenMPClause();
1627 }
1628}
1629
1630void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
1631 SourceLocation Loc) {
1632 SmallVector<std::string, 4> Assumptions;
1633 bool SkippedClauses = false;
1634
1635 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
1636 BalancedDelimiterTracker T(*this, tok::l_paren,
1637 tok::annot_pragma_openmp_end);
1638 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1639 return;
1640 T.skipToEnd();
1641 if (IssueNote && T.getCloseLocation().isValid())
1642 Diag(T.getCloseLocation(),
1643 diag::note_omp_assumption_clause_continue_here);
1644 };
1645
1646 /// Helper to determine which AssumptionClauseMapping (ACM) in the
1647 /// AssumptionClauseMappings table matches \p RawString. The return value is
1648 /// the index of the matching ACM into the table or -1 if there was no match.
1649 auto MatchACMClause = [&](StringRef RawString) {
1650 llvm::StringSwitch<int> SS(RawString);
1651 unsigned ACMIdx = 0;
1652 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1653 if (ACMI.StartsWith)
1654 SS.StartsWith(ACMI.Identifier, ACMIdx++);
1655 else
1656 SS.Case(ACMI.Identifier, ACMIdx++);
1657 }
1658 return SS.Default(-1);
1659 };
1660
1661 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1662 IdentifierInfo *II = nullptr;
1663 SourceLocation StartLoc = Tok.getLocation();
1664 int Idx = -1;
1665 if (Tok.isAnyIdentifier()) {
1666 II = Tok.getIdentifierInfo();
1667 Idx = MatchACMClause(II->getName());
1668 }
1670
1671 bool NextIsLPar = Tok.is(tok::l_paren);
1672 // Handle unknown clauses by skipping them.
1673 if (Idx == -1) {
1674 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1675 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1676 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion)
1677 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1678 if (NextIsLPar)
1679 SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
1680 SkippedClauses = true;
1681 continue;
1682 }
1683 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1684 if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1685 // TODO: We ignore absent, contains, and holds assumptions for now. We
1686 // also do not verify the content in the parenthesis at all.
1687 SkippedClauses = true;
1688 SkipBraces(II->getName(), /* IssueNote */ false);
1689 continue;
1690 }
1691
1692 if (NextIsLPar) {
1693 Diag(Tok.getLocation(),
1694 diag::warn_omp_unknown_assumption_clause_without_args)
1695 << II;
1696 SkipBraces(II->getName(), /* IssueNote */ true);
1697 }
1698
1699 assert(II && "Expected an identifier clause!");
1700 std::string Assumption = II->getName().str();
1701 if (ACMI.StartsWith)
1702 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
1703 else
1704 Assumption = "omp_" + Assumption;
1705 Assumptions.push_back(Assumption);
1706 }
1707
1708 Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
1709 SkippedClauses);
1710}
1711
1712void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
1713 if (Actions.OpenMP().isInOpenMPAssumeScope())
1714 Actions.OpenMP().ActOnOpenMPEndAssumesDirective();
1715 else
1716 Diag(Loc, diag::err_expected_begin_assumes);
1717}
1718
1719/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1720///
1721/// default-clause:
1722/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')
1723///
1724/// proc_bind-clause:
1725/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1726///
1727/// device_type-clause:
1728/// 'device_type' '(' 'host' | 'nohost' | 'any' )'
1729namespace {
1730struct SimpleClauseData {
1731 unsigned Type;
1732 SourceLocation Loc;
1733 SourceLocation LOpen;
1734 SourceLocation TypeLoc;
1735 SourceLocation RLoc;
1736 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1737 SourceLocation TypeLoc, SourceLocation RLoc)
1738 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1739};
1740} // anonymous namespace
1741
1742static std::optional<SimpleClauseData>
1744 const Token &Tok = P.getCurToken();
1745 SourceLocation Loc = Tok.getLocation();
1746 SourceLocation LOpen = P.ConsumeToken();
1747 // Parse '('.
1748 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1749 if (T.expectAndConsume(diag::err_expected_lparen_after,
1750 getOpenMPClauseName(Kind).data()))
1751 return std::nullopt;
1752
1754 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1755 P.getLangOpts());
1756 SourceLocation TypeLoc = Tok.getLocation();
1757 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1758 Tok.isNot(tok::annot_pragma_openmp_end))
1759 P.ConsumeAnyToken();
1760
1761 // Parse ')'.
1762 SourceLocation RLoc = Tok.getLocation();
1763 if (!T.consumeClose())
1764 RLoc = T.getCloseLocation();
1765
1766 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1767}
1768
1769void Parser::ParseOMPDeclareTargetClauses(
1771 SourceLocation DeviceTypeLoc;
1772 bool RequiresToLinkLocalOrIndirectClause = false;
1773 bool HasToLinkLocalOrIndirectClause = false;
1774 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1775 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1776 bool HasIdentifier = Tok.is(tok::identifier);
1777 if (HasIdentifier) {
1778 // If we see any clause we need a to, link, or local clause.
1779 RequiresToLinkLocalOrIndirectClause = true;
1780 IdentifierInfo *II = Tok.getIdentifierInfo();
1781 StringRef ClauseName = II->getName();
1782 bool IsDeviceTypeClause =
1783 getLangOpts().OpenMP >= 50 &&
1784 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1785
1786 bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1787 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1788
1789 if (DTCI.Indirect && IsIndirectClause) {
1790 llvm::omp::Version OMPVersion =
1791 Actions.getLangOpts().getOpenMPVersion();
1792 Diag(Tok, diag::err_omp_more_one_clause)
1793 << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)
1794 << getOpenMPClauseName(OMPC_indirect) << 0;
1795 break;
1796 }
1797 bool IsToEnterLinkOrLocalClause =
1798 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1799 assert((!IsDeviceTypeClause || !IsToEnterLinkOrLocalClause) &&
1800 "Cannot be both!");
1801
1802 // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1803 // `enter` clause.
1804 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1805 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1806 break;
1807 }
1808 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1809 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1810 break;
1811 }
1812
1813 // The 'local' clause is only available in OpenMP 6.0.
1814 if (getLangOpts().OpenMP < 60 && ClauseName == "local") {
1815 Diag(Tok, getLangOpts().OpenMP >= 52
1816 ? diag::err_omp_declare_target_unexpected_clause_52
1817 : diag::err_omp_declare_target_unexpected_clause)
1818 << ClauseName
1819 << (getLangOpts().OpenMP >= 51 ? 4
1820 : getLangOpts().OpenMP >= 50 ? 2
1821 : 1);
1822 break;
1823 }
1824
1825 if (!IsDeviceTypeClause && !IsIndirectClause &&
1826 DTCI.Kind == OMPD_begin_declare_target) {
1827 Diag(Tok, getLangOpts().OpenMP >= 52
1828 ? diag::err_omp_declare_target_unexpected_clause_52
1829 : diag::err_omp_declare_target_unexpected_clause)
1830 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
1831 break;
1832 }
1833
1834 if (!IsDeviceTypeClause && !IsToEnterLinkOrLocalClause &&
1835 !IsIndirectClause) {
1836 Diag(Tok, getLangOpts().OpenMP >= 52
1837 ? diag::err_omp_declare_target_unexpected_clause_52
1838 : diag::err_omp_declare_target_unexpected_clause)
1839 << ClauseName
1840 << (getLangOpts().OpenMP > 52 ? 5
1841 : getLangOpts().OpenMP >= 51 ? 4
1842 : getLangOpts().OpenMP >= 50 ? 2
1843 : 1);
1844 break;
1845 }
1846
1847 if (IsToEnterLinkOrLocalClause || IsIndirectClause)
1848 HasToLinkLocalOrIndirectClause = true;
1849
1850 if (IsIndirectClause) {
1851 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1852 break;
1853 continue;
1854 }
1855 // Parse 'device_type' clause and go to next clause if any.
1856 if (IsDeviceTypeClause) {
1857 std::optional<SimpleClauseData> DevTypeData =
1858 parseOpenMPSimpleClause(*this, OMPC_device_type);
1859 if (DevTypeData) {
1860 if (DeviceTypeLoc.isValid()) {
1861 // We already saw another device_type clause, diagnose it.
1862 Diag(DevTypeData->Loc,
1863 diag::warn_omp_more_one_device_type_clause);
1864 break;
1865 }
1866 switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1867 case OMPC_DEVICE_TYPE_any:
1868 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1869 break;
1870 case OMPC_DEVICE_TYPE_host:
1871 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1872 break;
1873 case OMPC_DEVICE_TYPE_nohost:
1874 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1875 break;
1877 llvm_unreachable("Unexpected device_type");
1878 }
1879 DeviceTypeLoc = DevTypeData->Loc;
1880 }
1881 continue;
1882 }
1883 ConsumeToken();
1884 }
1885
1886 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1887 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1888 DeclarationNameInfo NameInfo) {
1889 NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
1890 getCurScope(), SS, NameInfo);
1891 if (!ND)
1892 return;
1893 SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
1894 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1895 if (!FirstMapping)
1896 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1897 << NameInfo.getName();
1898 };
1899 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1900 /*AllowScopeSpecifier=*/true))
1901 break;
1902 }
1903
1904 if (Tok.is(tok::l_paren)) {
1905 Diag(Tok,
1906 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1907 break;
1908 }
1909 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1910 Diag(Tok,
1911 getLangOpts().OpenMP >= 52
1912 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1913 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1914 break;
1915 }
1916
1917 // Consume optional ','.
1918 if (Tok.is(tok::comma))
1919 ConsumeToken();
1920 }
1921
1922 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1923 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1924
1925 // declare target requires at least one clause.
1926 if (DTCI.Kind == OMPD_declare_target && RequiresToLinkLocalOrIndirectClause &&
1927 !HasToLinkLocalOrIndirectClause)
1928 Diag(DTCI.Loc, diag::err_omp_declare_target_missing_required_clause)
1929 << (getLangOpts().OpenMP >= 60 ? 3
1930 : getLangOpts().OpenMP == 52 ? 2
1931 : getLangOpts().OpenMP == 51 ? 1
1932 : 0);
1933
1934 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1935}
1936
1937void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1938 // The last seen token is annot_pragma_openmp_end - need to check for
1939 // extra tokens.
1940 if (Tok.is(tok::annot_pragma_openmp_end))
1941 return;
1942
1943 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1944 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1945 << getOpenMPDirectiveName(DKind, OMPVersion);
1946 while (Tok.isNot(tok::annot_pragma_openmp_end))
1948}
1949
1950void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1951 OpenMPDirectiveKind ExpectedKind,
1952 OpenMPDirectiveKind FoundKind,
1953 SourceLocation BeginLoc,
1954 SourceLocation FoundLoc,
1955 bool SkipUntilOpenMPEnd) {
1956 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1957
1958 if (FoundKind == ExpectedKind) {
1960 skipUntilPragmaOpenMPEnd(ExpectedKind);
1961 return;
1962 }
1963
1964 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1965 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1966 << DiagSelection;
1967 Diag(BeginLoc, diag::note_matching)
1968 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + "'")
1969 .str();
1970 if (SkipUntilOpenMPEnd)
1971 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1972}
1973
1974void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
1975 OpenMPDirectiveKind EndDKind,
1976 SourceLocation DKLoc) {
1977 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
1978 Tok.getLocation(),
1979 /* SkipUntilOpenMPEnd */ false);
1980 // Skip the last annot_pragma_openmp_end.
1981 if (Tok.is(tok::annot_pragma_openmp_end))
1982 ConsumeAnnotationToken();
1983}
1984
1985Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1986 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
1987 DeclSpec::TST TagType, Decl *Tag) {
1988 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
1989 "Not an OpenMP directive!");
1990 ParsingOpenMPDirectiveRAII DirScope(*this);
1991 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1992 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
1993
1994 SourceLocation Loc;
1995 OpenMPDirectiveKind DKind;
1996 if (Delayed) {
1997 TentativeParsingAction TPA(*this);
1998 Loc = ConsumeAnnotationToken();
1999 DKind = parseOpenMPDirectiveKind(*this);
2000 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
2001 // Need to delay parsing until completion of the parent class.
2002 TPA.Revert();
2003 CachedTokens Toks;
2004 unsigned Cnt = 1;
2005 Toks.push_back(Tok);
2006 while (Cnt && Tok.isNot(tok::eof)) {
2007 (void)ConsumeAnyToken();
2008 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2009 ++Cnt;
2010 else if (Tok.is(tok::annot_pragma_openmp_end))
2011 --Cnt;
2012 Toks.push_back(Tok);
2013 }
2014 // Skip last annot_pragma_openmp_end.
2015 if (Cnt == 0)
2016 (void)ConsumeAnyToken();
2017 auto *LP = new LateParsedPragma(this, AS);
2018 LP->takeToks(Toks);
2019 getCurrentClass().LateParsedDeclarations.push_back(LP);
2020 return nullptr;
2021 }
2022 TPA.Commit();
2023 } else {
2024 Loc = ConsumeAnnotationToken();
2025 DKind = parseOpenMPDirectiveKind(*this);
2026 }
2027
2028 switch (DKind) {
2029 case OMPD_threadprivate: {
2030 ConsumeToken();
2031 DeclDirectiveListParserHelper Helper(this, DKind);
2032 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2033 /*AllowScopeSpecifier=*/true)) {
2034 skipUntilPragmaOpenMPEnd(DKind);
2035 // Skip the last annot_pragma_openmp_end.
2036 ConsumeAnnotationToken();
2037 return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2038 Loc, Helper.getIdentifiers());
2039 }
2040 break;
2041 }
2042 case OMPD_groupprivate: {
2043 ConsumeToken();
2044 DeclDirectiveListParserHelper Helper(this, DKind);
2045 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2046 /*AllowScopeSpecifier=*/true)) {
2047 skipUntilPragmaOpenMPEnd(DKind);
2048 // Skip the last annot_pragma_openmp_end.
2049 ConsumeAnnotationToken();
2050 return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2051 Loc, Helper.getIdentifiers());
2052 }
2053 break;
2054 }
2055 case OMPD_allocate: {
2056 ConsumeToken();
2057 DeclDirectiveListParserHelper Helper(this, DKind);
2058 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2059 /*AllowScopeSpecifier=*/true)) {
2060 SmallVector<OMPClause *, 1> Clauses;
2061 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2062 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
2063 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2064 OpenMPClauseKind CKind =
2065 Tok.isAnnotation() ? OMPC_unknown
2066 : getOpenMPClauseKind(PP.getSpelling(Tok));
2067 Actions.OpenMP().StartOpenMPClause(CKind);
2068 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2069 !SeenClauses[unsigned(CKind)]);
2070 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2072 SeenClauses[unsigned(CKind)] = true;
2073 if (Clause != nullptr)
2074 Clauses.push_back(Clause);
2075 if (Tok.is(tok::annot_pragma_openmp_end)) {
2076 Actions.OpenMP().EndOpenMPClause();
2077 break;
2078 }
2079 // Skip ',' if any.
2080 if (Tok.is(tok::comma))
2081 ConsumeToken();
2082 Actions.OpenMP().EndOpenMPClause();
2083 }
2084 skipUntilPragmaOpenMPEnd(DKind);
2085 }
2086 // Skip the last annot_pragma_openmp_end.
2087 ConsumeAnnotationToken();
2088 return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2089 Loc, Helper.getIdentifiers(), Clauses);
2090 }
2091 break;
2092 }
2093 case OMPD_requires: {
2094 SourceLocation StartLoc = ConsumeToken();
2095 SmallVector<OMPClause *, 5> Clauses;
2096 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2097 if (Tok.is(tok::annot_pragma_openmp_end)) {
2098 Diag(Tok, diag::err_omp_expected_clause)
2099 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2100 break;
2101 }
2102 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2103 OpenMPClauseKind CKind = Tok.isAnnotation()
2104 ? OMPC_unknown
2105 : getOpenMPClauseKind(PP.getSpelling(Tok));
2106 Actions.OpenMP().StartOpenMPClause(CKind);
2107 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
2108 !SeenClauses[unsigned(CKind)]);
2109 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2111 SeenClauses[unsigned(CKind)] = true;
2112 if (Clause != nullptr)
2113 Clauses.push_back(Clause);
2114 if (Tok.is(tok::annot_pragma_openmp_end)) {
2115 Actions.OpenMP().EndOpenMPClause();
2116 break;
2117 }
2118 // Skip ',' if any.
2119 if (Tok.is(tok::comma))
2120 ConsumeToken();
2121 Actions.OpenMP().EndOpenMPClause();
2122 }
2123 // Consume final annot_pragma_openmp_end
2124 if (Clauses.empty()) {
2125 Diag(Tok, diag::err_omp_expected_clause)
2126 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2127 ConsumeAnnotationToken();
2128 return nullptr;
2129 }
2130 ConsumeAnnotationToken();
2131 return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
2132 }
2133 case OMPD_error: {
2134 SmallVector<OMPClause *, 1> Clauses;
2135 SourceLocation StartLoc = ConsumeToken();
2136 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2137 Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2138 SourceLocation(),
2139 /*InExContext = */ false);
2140 break;
2141 }
2142 case OMPD_assumes:
2143 case OMPD_begin_assumes:
2144 ParseOpenMPAssumesDirective(DKind, ConsumeToken());
2145 break;
2146 case OMPD_end_assumes:
2147 ParseOpenMPEndAssumesDirective(ConsumeToken());
2148 break;
2149 case OMPD_declare_reduction:
2150 ConsumeToken();
2151 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2152 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2153 // Skip the last annot_pragma_openmp_end.
2154 ConsumeAnnotationToken();
2155 return Res;
2156 }
2157 break;
2158 case OMPD_declare_mapper: {
2159 ConsumeToken();
2160 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2161 // Skip the last annot_pragma_openmp_end.
2162 ConsumeAnnotationToken();
2163 return Res;
2164 }
2165 break;
2166 }
2167 case OMPD_begin_declare_variant: {
2168 ConsumeToken();
2170 // Skip the last annot_pragma_openmp_end.
2171 if (!isEofOrEom())
2172 ConsumeAnnotationToken();
2173 }
2174 return nullptr;
2175 }
2176 case OMPD_end_declare_variant: {
2177 ConsumeToken();
2178 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2179 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2180 else
2181 Diag(Loc, diag::err_expected_begin_declare_variant);
2182 // Skip the last annot_pragma_openmp_end.
2183 ConsumeAnnotationToken();
2184 return nullptr;
2185 }
2186 case OMPD_declare_variant:
2187 case OMPD_declare_simd: {
2188 // The syntax is:
2189 // { #pragma omp declare {simd|variant} }
2190 // <function-declaration-or-definition>
2191 //
2192 CachedTokens Toks;
2193 Toks.push_back(Tok);
2194 ConsumeToken();
2195 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2196 Toks.push_back(Tok);
2198 }
2199 Toks.push_back(Tok);
2201
2203 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2204 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2205 TagType, Tag);
2206 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
2207 // Here we expect to see some function declaration.
2208 if (AS == AS_none) {
2209 assert(TagType == DeclSpec::TST_unspecified);
2210 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2211 MaybeParseCXX11Attributes(Attrs);
2212 ParsingDeclSpec PDS(*this);
2213 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2214 } else {
2215 Ptr =
2216 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
2217 }
2218 }
2219 if (!Ptr) {
2220 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2221 << (DKind == OMPD_declare_simd ? 0 : 1);
2222 return DeclGroupPtrTy();
2223 }
2224
2225 DeclGroupRef DG = Ptr.get();
2226 SourceManager &SM = PP.getSourceManager();
2227 if (llvm::none_of(DG, [&](const Decl *D) {
2228 return SM.isBeforeInTranslationUnit(Loc, D->getBeginLoc());
2229 })) {
2230 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2231 << (DKind == OMPD_declare_simd ? 0 : 1);
2232 return DeclGroupPtrTy();
2233 }
2234
2235 if (DKind == OMPD_declare_simd)
2236 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2237 assert(DKind == OMPD_declare_variant &&
2238 "Expected declare variant directive only");
2239 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2240 return Ptr;
2241 }
2242 case OMPD_begin_declare_target:
2243 case OMPD_declare_target: {
2244 SourceLocation DTLoc = ConsumeAnyToken();
2245 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2246 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2247 if (DKind == OMPD_declare_target && !HasClauses &&
2248 getLangOpts().OpenMP >= 52)
2249 Diag(DTLoc, diag::warn_omp_deprecated_declare_target_delimited_form);
2250 if (HasClauses)
2251 ParseOMPDeclareTargetClauses(DTCI);
2252 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2253 !HasClauses ||
2254 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2255
2256 // Skip the last annot_pragma_openmp_end.
2258
2259 if (HasImplicitMappings) {
2260 Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
2261 return nullptr;
2262 }
2263
2264 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2265 llvm::SmallVector<Decl *, 4> Decls;
2266 for (auto &It : DTCI.ExplicitlyMapped)
2267 Decls.push_back(It.first);
2268 return Actions.BuildDeclaratorGroup(Decls);
2269 }
2270 case OMPD_end_declare_target: {
2271 if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2272 Diag(Tok, diag::err_omp_unexpected_directive)
2273 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2274 break;
2275 }
2276 const SemaOpenMP::DeclareTargetContextInfo &DTCI =
2277 Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
2278 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2279 return nullptr;
2280 }
2281 case OMPD_assume: {
2282 Diag(Tok, diag::err_omp_unexpected_directive)
2283 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2284 break;
2285 }
2286 case OMPD_unknown:
2287 Diag(Tok, diag::err_omp_unknown_directive);
2288 break;
2289 default:
2290 switch (getDirectiveCategory(DKind)) {
2291 case Category::Executable:
2292 case Category::Meta:
2293 case Category::Subsidiary:
2294 case Category::Utility:
2295 Diag(Tok, diag::err_omp_unexpected_directive)
2296 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2297 break;
2298 case Category::Declarative:
2299 case Category::Informational:
2300 break;
2301 }
2302 }
2303 while (Tok.isNot(tok::annot_pragma_openmp_end))
2306 return nullptr;
2307}
2308
2309StmtResult Parser::ParseOpenMPExecutableDirective(
2310 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2311 bool ReadDirectiveWithinMetadirective) {
2312 assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2313 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
2314
2315 bool HasAssociatedStatement = true;
2316 Association Assoc = getDirectiveAssociation(DKind);
2317
2318 // OMPD_scan and OMPD_section are both "separating", but section is treated
2319 // as if it was associated with a statement, while scan is not.
2320 if (DKind != OMPD_ordered_standalone && DKind != OMPD_section &&
2321 (Assoc == Association::None || Assoc == Association::Separating)) {
2322 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2323 ParsedStmtContext()) {
2324 Diag(Tok, diag::err_omp_immediate_directive)
2325 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2326 if (DKind == OMPD_error) {
2327 SkipUntil(tok::annot_pragma_openmp_end);
2328 return StmtError();
2329 }
2330 }
2331 HasAssociatedStatement = false;
2332 }
2333
2334 SourceLocation EndLoc;
2335 SmallVector<OMPClause *, 5> Clauses;
2336 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2337 DeclarationNameInfo DirName;
2338 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2339 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2341
2342 // Special processing for flush and depobj clauses.
2343 Token ImplicitTok;
2344 bool ImplicitClauseAllowed = false;
2345 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2346 ImplicitTok = Tok;
2347 ImplicitClauseAllowed = true;
2348 }
2349 ConsumeToken();
2350 // Parse directive name of the 'critical' directive if any.
2351 if (DKind == OMPD_critical) {
2352 BalancedDelimiterTracker T(*this, tok::l_paren,
2353 tok::annot_pragma_openmp_end);
2354 if (!T.consumeOpen()) {
2355 if (Tok.isAnyIdentifier()) {
2356 DirName =
2357 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2359 } else {
2360 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2361 }
2362 T.consumeClose();
2363 }
2364 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2365 CancelRegion = parseOpenMPDirectiveKind(*this);
2366 if (Tok.isNot(tok::annot_pragma_openmp_end))
2368 }
2369
2370 if (isOpenMPLoopDirective(DKind))
2371 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2372 if (isOpenMPSimdDirective(DKind))
2373 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2374 ParseScope OMPDirectiveScope(this, ScopeFlags);
2375 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2376 Loc);
2377
2378 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2379 // If we are parsing for a directive within a metadirective, the directive
2380 // ends with a ')'.
2381 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2382 while (Tok.isNot(tok::annot_pragma_openmp_end))
2384 break;
2385 }
2386 bool HasImplicitClause = false;
2387 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2388 HasImplicitClause = true;
2389 // Push copy of the current token back to stream to properly parse
2390 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2391 PP.EnterToken(Tok, /*IsReinject*/ true);
2392 PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2394 }
2395 OpenMPClauseKind CKind = Tok.isAnnotation()
2396 ? OMPC_unknown
2397 : getOpenMPClauseKind(PP.getSpelling(Tok));
2398 if (DKind == OMPD_depobj && CKind == OMPC_update)
2399 CKind = OMPC_update_depend_objects;
2400
2401 if (HasImplicitClause) {
2402 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2403 if (DKind == OMPD_flush) {
2404 CKind = OMPC_flush;
2405 } else {
2406 assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2407 CKind = OMPC_depobj;
2408 }
2409 }
2410 // No more implicit clauses allowed.
2411 ImplicitClauseAllowed = false;
2412 Actions.OpenMP().StartOpenMPClause(CKind);
2413 HasImplicitClause = false;
2414 SourceLocation ClauseLoc = Tok.getLocation();
2415
2416 OMPClause *Clause =
2417 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2418 SeenClauses[unsigned(CKind)] = true;
2419 if (Clause)
2420 Clauses.push_back(Clause);
2421
2422 // Skip ',' if any.
2423 if (Tok.is(tok::comma))
2424 ConsumeToken();
2425 Actions.OpenMP().EndOpenMPClause();
2426
2427 // If ParseOpenMPClause returned without consuming any tokens, skip
2428 // to end to avoid an infinite loop.
2429 if (Tok.getLocation() == ClauseLoc) {
2430 skipUntilPragmaOpenMPEnd(DKind);
2431 break;
2432 }
2433 }
2434 // End location of the directive.
2435 EndLoc = Tok.getLocation();
2436 // Consume final annot_pragma_openmp_end.
2437 ConsumeAnnotationToken();
2438
2439 assert(DKind != OMPD_ordered_blockassoc &&
2440 "Wrong kind for ordered directive");
2441 if (DKind == OMPD_ordered_standalone) {
2442 // If the depend or doacross clause is specified, the ordered construct
2443 // is a stand-alone directive.
2444 for (auto CK : {OMPC_depend, OMPC_doacross}) {
2445 if (SeenClauses[unsigned(CK)]) {
2446 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2447 ParsedStmtContext()) {
2448 Diag(Loc, diag::err_omp_immediate_directive)
2449 << getOpenMPDirectiveName(DKind, OMPVersion) << 1
2450 << getOpenMPClauseName(CK);
2451 }
2452 HasAssociatedStatement = false;
2453 }
2454 }
2455
2456 if (HasAssociatedStatement)
2457 DKind = OMPD_ordered_blockassoc;
2458 }
2459
2460 if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
2461 !SeenClauses[unsigned(OMPC_sizes)]) {
2462 Diag(Loc, diag::err_omp_required_clause)
2463 << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";
2464 }
2465 if (DKind == OMPD_split && !SeenClauses[unsigned(OMPC_counts)]) {
2466 Diag(Loc, diag::err_omp_required_clause)
2467 << getOpenMPDirectiveName(DKind, OMPVersion) << "counts";
2468 }
2469
2470 StmtResult AssociatedStmt;
2471 if (HasAssociatedStatement) {
2472 // The body is a block scope like in Lambdas and Blocks.
2473 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2474 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2475 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2476 // should have at least one compound statement scope within it.
2477 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2478 {
2479 Sema::CompoundScopeRAII Scope(Actions);
2480 AssociatedStmt = ParseStatement();
2481
2482 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2483 getLangOpts().OpenMPIRBuilder)
2484 AssociatedStmt =
2485 Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2486 }
2487 AssociatedStmt =
2488 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2489 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2490 DKind == OMPD_target_exit_data) {
2491 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2492 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2493 Actions.ActOnCompoundStmt(Loc, Loc, {},
2494 /*isStmtExpr=*/false));
2495 AssociatedStmt =
2496 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2497 }
2498
2499 StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
2500 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2501
2502 // Exit scope.
2503 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2504 OMPDirectiveScope.Exit();
2505
2506 return Directive;
2507}
2508
2509StmtResult Parser::ParseOpenMPInformationalDirective(
2510 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2511 bool ReadDirectiveWithinMetadirective) {
2512 assert(isOpenMPInformationalDirective(DKind) &&
2513 "Unexpected directive category");
2514
2515 bool HasAssociatedStatement = true;
2516
2517 SmallVector<OMPClause *, 5> Clauses;
2518 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2519 DeclarationNameInfo DirName;
2520 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2522 ParseScope OMPDirectiveScope(this, ScopeFlags);
2523
2524 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2525 Loc);
2526
2527 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2528 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2529 while (Tok.isNot(tok::annot_pragma_openmp_end))
2531 break;
2532 }
2533
2534 OpenMPClauseKind CKind = Tok.isAnnotation()
2535 ? OMPC_unknown
2536 : getOpenMPClauseKind(PP.getSpelling(Tok));
2537 Actions.OpenMP().StartOpenMPClause(CKind);
2538 OMPClause *Clause =
2539 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2540 SeenClauses[unsigned(CKind)] = true;
2541 if (Clause)
2542 Clauses.push_back(Clause);
2543
2544 if (Tok.is(tok::comma))
2545 ConsumeToken();
2546 Actions.OpenMP().EndOpenMPClause();
2547 }
2548
2549 SourceLocation EndLoc = Tok.getLocation();
2550 ConsumeAnnotationToken();
2551
2552 StmtResult AssociatedStmt;
2553 if (HasAssociatedStatement) {
2554 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2555 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2556 {
2557 Sema::CompoundScopeRAII Scope(Actions);
2558 AssociatedStmt = ParseStatement();
2559 }
2560 AssociatedStmt =
2561 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2562 }
2563
2564 StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
2565 DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2566
2567 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2568 OMPDirectiveScope.Exit();
2569
2570 return Directive;
2571}
2572
2573StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2574 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2575 if (!ReadDirectiveWithinMetadirective)
2576 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2577 "Not an OpenMP directive!");
2578 ParsingOpenMPDirectiveRAII DirScope(*this);
2579 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2580 SourceLocation Loc = ReadDirectiveWithinMetadirective
2581 ? Tok.getLocation()
2582 : ConsumeAnnotationToken();
2583 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
2585 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2586 Diag(Tok, diag::err_omp_unknown_directive);
2587 return StmtError();
2588 }
2589
2591
2592 bool IsExecutable = [&]() {
2593 if (DKind == OMPD_error) // OMPD_error is handled as executable
2594 return true;
2595 auto Res = getDirectiveCategory(DKind);
2596 return Res == Category::Executable || Res == Category::Subsidiary;
2597 }();
2598
2599 if (IsExecutable) {
2600 Directive = ParseOpenMPExecutableDirective(
2601 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2602 assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2603 return Directive;
2604 }
2605
2606 switch (DKind) {
2607 case OMPD_nothing:
2608 ConsumeToken();
2609 // If we are parsing the directive within a metadirective, the directive
2610 // ends with a ')'.
2611 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
2612 while (Tok.isNot(tok::annot_pragma_openmp_end))
2614 else
2615 skipUntilPragmaOpenMPEnd(DKind);
2616 if (Tok.is(tok::annot_pragma_openmp_end))
2617 ConsumeAnnotationToken();
2618 // return an empty statement
2619 return StmtEmpty();
2620 case OMPD_metadirective: {
2621 ConsumeToken();
2622 SmallVector<VariantMatchInfo, 4> VMIs;
2623 SmallVector<OMPTraitInfo *, 4> TraitInfos;
2624
2625 // First iteration of parsing all clauses of metadirective.
2626 // This iteration only parses and collects all context selectors ignoring
2627 // the associated directives.
2628 TentativeParsingAction TPA(*this);
2629 ASTContext &ASTContext = Actions.getASTContext();
2630
2631 BalancedDelimiterTracker T(*this, tok::l_paren,
2632 tok::annot_pragma_openmp_end);
2633 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2634 OpenMPClauseKind CKind = Tok.isAnnotation()
2635 ? OMPC_unknown
2636 : getOpenMPClauseKind(PP.getSpelling(Tok));
2637 // Check if the clause is unrecognized.
2638 if (CKind == OMPC_unknown) {
2639 Diag(Tok, diag::err_omp_expected_clause) << "metadirective";
2640 TPA.Revert();
2641 SkipUntil(tok::annot_pragma_openmp_end);
2642 return Directive;
2643 }
2644 if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)
2645 Diag(Tok, diag::err_omp_unexpected_clause)
2646 << getOpenMPClauseName(CKind) << "metadirective";
2647 if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)
2648 Diag(Tok, diag::warn_omp_default_deprecated);
2649
2650 SourceLocation Loc = ConsumeToken();
2651
2652 // Parse '('.
2653 if (T.expectAndConsume(diag::err_expected_lparen_after,
2654 getOpenMPClauseName(CKind).data())) {
2655 TPA.Revert();
2656 SkipUntil(tok::annot_pragma_openmp_end);
2657 return Directive;
2658 }
2659
2660 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2661 if (CKind == OMPC_when) {
2662 // parse and get OMPTraitInfo to pass to the When clause
2663 parseOMPContextSelectors(Loc, TI);
2664 if (TI.Sets.size() == 0) {
2665 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2666 TPA.Commit();
2667 return Directive;
2668 }
2669
2670 // Parse ':'
2671 if (Tok.is(tok::colon))
2673 else {
2674 Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2675 TPA.Commit();
2676 return Directive;
2677 }
2678 }
2679
2680 // Skip Directive for now. We will parse directive in the second iteration
2681 int paren = 0;
2682 while (Tok.isNot(tok::r_paren) || paren != 0) {
2683 if (Tok.is(tok::l_paren))
2684 paren++;
2685 if (Tok.is(tok::r_paren))
2686 paren--;
2687 if (Tok.is(tok::annot_pragma_openmp_end)) {
2688 Diag(Tok, diag::err_omp_expected_punc)
2689 << getOpenMPClauseName(CKind) << 0;
2690 TPA.Commit();
2691 return Directive;
2692 }
2694 }
2695 // Parse ')'
2696 if (Tok.is(tok::r_paren))
2697 T.consumeClose();
2698
2699 VariantMatchInfo VMI;
2700 TI.getAsVariantMatchInfo(ASTContext, VMI);
2701
2702 VMIs.push_back(VMI);
2703 TraitInfos.push_back(&TI);
2704 }
2705
2706 SourceLocation EndLoc = Tok.getLocation();
2707 TPA.Revert();
2708 // End of the first iteration. Parser is reset to the start of metadirective
2709
2710 std::function<void(StringRef)> DiagUnknownTrait =
2711 [this, Loc](StringRef ISATrait) {
2712 // TODO Track the selector locations in a way that is accessible here
2713 // to improve the diagnostic location.
2714 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2715 };
2716 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2717 /* CurrentFunctionDecl */ nullptr,
2718 ArrayRef<llvm::omp::TraitProperty>(),
2719 Actions.OpenMP().getOpenMPDeviceNum());
2720
2721 // A single match is returned for OpenMP 5.0
2722 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2723
2724 // Check if we have user conditions with non-constant expressions that
2725 // require runtime selection.
2726 bool HasNonConstUserCondition =
2727 llvm::any_of(TraitInfos, [&](OMPTraitInfo *TI) {
2728 return TI->anyScoreOrCondition([&](Expr *&E, bool IsScore) {
2729 return !IsScore && E && !E->getIntegerConstantExpr(ASTContext);
2730 });
2731 });
2732
2733 if (HasNonConstUserCondition &&
2734 getLangOpts().OpenMPMetadirectiveRuntimeSelection) {
2735 // OpenMP 5.2, 7.4: without an 'otherwise' clause the effect is as if one
2736 // was specified without an associated directive variant. Only
2737 // 'otherwise' (or the deprecated 'default') has no context selectors.
2738 unsigned NumClauses = TraitInfos.size();
2739 if (llvm::none_of(TraitInfos, [](const OMPTraitInfo *TI) {
2740 return TI->Sets.empty();
2741 }))
2742 TraitInfos.push_back(&ASTContext.getNewOMPTraitInfo());
2743
2744 // Reuse the normal metadirective variant parse per clause so every
2745 // variant is a complete directive node with its own body and its own
2746 // data-sharing context. Diagnostics in the associated statement are
2747 // reported once per variant.
2748 SmallVector<Stmt *, 4> Variants;
2749 bool HasError = false;
2750 for (unsigned I : llvm::seq<unsigned>(TraitInfos.size())) {
2751 bool HasDirective = false;
2752 if (I < NumClauses) {
2753 OpenMPClauseKind CKind = getOpenMPClauseKind(PP.getSpelling(Tok));
2754 ConsumeToken();
2755 T.consumeOpen();
2756 if (CKind == OMPC_when) {
2757 // The selectors were parsed into TraitInfos[I] by the first pass;
2758 // skip them so their diagnostics are not repeated.
2759 SkipUntil(tok::colon, StopBeforeMatch);
2760 TryConsumeToken(tok::colon);
2761 }
2762 HasDirective = Tok.isNot(tok::r_paren) &&
2763 Tok.isNot(tok::annot_pragma_openmp_end);
2764 }
2765 // Re-parse the directive and body for every variant but the last.
2766 std::optional<TentativeParsingAction> VariantTPA;
2767 if (I + 1 < TraitInfos.size())
2768 VariantTPA.emplace(*this, /*Unannotated=*/true);
2769
2770 StmtResult Variant;
2771 if (HasDirective) {
2772 Variant = ParseOpenMPDeclarativeOrExecutableDirective(
2773 StmtCtx, /*ReadDirectiveWithinMetadirective=*/true);
2774 } else {
2775 // No directive variant: skip to the end of the pragma.
2776 while (Tok.isNot(tok::annot_pragma_openmp_end))
2778 ConsumeAnnotationToken();
2779 }
2780 // No directive or 'nothing': the variant is the associated statement.
2781 if (!Variant.isInvalid() && !Variant.isUsable()) {
2782 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2783 Variant = ParseStatement();
2784 }
2785 // A standalone variant does not take the associated statement while
2786 // the others do; reject the mix until Sema models it.
2787 if (auto *D = dyn_cast_or_null<OMPExecutableDirective>(Variant.get());
2788 D && !D->hasAssociatedStmt()) {
2789 Diag(Loc, diag::err_omp_metadirective_standalone_variant);
2790 Variant = StmtError();
2791 }
2792
2793 if (VariantTPA) {
2794 VariantTPA->Revert();
2795 SkipUntil(tok::r_paren, StopBeforeMatch);
2796 T.consumeClose();
2797 }
2798 if (Variant.isInvalid())
2799 HasError = true;
2800 else
2801 Variants.push_back(Variant.get());
2802 }
2803 if (HasError)
2804 return StmtError();
2805 return Actions.OpenMP().ActOnOpenMPMetaDirective(Loc, EndLoc, TraitInfos,
2806 Variants);
2807 }
2808
2809 int Idx = 0;
2810 // In OpenMP 5.0 metadirective is either replaced by another directive or
2811 // ignored.
2812 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2813 // found by getBestWhenMatchForContext.
2814 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2815 // OpenMP 5.0 implementation - Skip to the best index found.
2816 if (Idx++ != BestIdx) {
2817 ConsumeToken(); // Consume clause name
2818 T.consumeOpen(); // Consume '('
2819 int paren = 0;
2820 // Skip everything inside the clause
2821 while (Tok.isNot(tok::r_paren) || paren != 0) {
2822 if (Tok.is(tok::l_paren))
2823 paren++;
2824 if (Tok.is(tok::r_paren))
2825 paren--;
2827 }
2828 // Parse ')'
2829 if (Tok.is(tok::r_paren))
2830 T.consumeClose();
2831 continue;
2832 }
2833
2834 OpenMPClauseKind CKind = Tok.isAnnotation()
2835 ? OMPC_unknown
2836 : getOpenMPClauseKind(PP.getSpelling(Tok));
2837 SourceLocation Loc = ConsumeToken();
2838
2839 // Parse '('.
2840 T.consumeOpen();
2841
2842 // Skip ContextSelectors for when clause
2843 if (CKind == OMPC_when) {
2844 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2845 // parse and skip the ContextSelectors
2846 parseOMPContextSelectors(Loc, TI);
2847
2848 // Parse ':'
2850 }
2851
2852 // If no directive is passed, skip in OpenMP 5.0.
2853 // TODO: Generate nothing directive from OpenMP 5.1.
2854 if (Tok.is(tok::r_paren)) {
2855 SkipUntil(tok::annot_pragma_openmp_end);
2856 break;
2857 }
2858
2859 // Parse Directive
2860 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2861 StmtCtx,
2862 /*ReadDirectiveWithinMetadirective=*/true);
2863 break;
2864 }
2865 // If no match is found and no otherwise clause is present, skip
2866 // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
2867 // if one was specified without an associated directive variant.
2868 if (BestIdx == -1 && Idx > 0) {
2869 assert(Tok.is(tok::annot_pragma_openmp_end) &&
2870 "Expecting the end of the pragma here");
2871 ConsumeAnnotationToken();
2872 return StmtEmpty();
2873 }
2874 break;
2875 }
2876 case OMPD_threadprivate: {
2877 // FIXME: Should this be permitted in C++?
2878 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2879 ParsedStmtContext()) {
2880 Diag(Tok, diag::err_omp_immediate_directive)
2881 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2882 }
2883 ConsumeToken();
2884 DeclDirectiveListParserHelper Helper(this, DKind);
2885 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2886 /*AllowScopeSpecifier=*/false)) {
2887 skipUntilPragmaOpenMPEnd(DKind);
2888 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2889 Loc, Helper.getIdentifiers());
2890 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2891 }
2892 SkipUntil(tok::annot_pragma_openmp_end);
2893 break;
2894 }
2895 case OMPD_groupprivate: {
2896 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2897 ParsedStmtContext()) {
2898 Diag(Tok, diag::err_omp_immediate_directive)
2899 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2900 }
2901 ConsumeToken();
2902 DeclDirectiveListParserHelper Helper(this, DKind);
2903 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2904 /*AllowScopeSpecifier=*/false)) {
2905 skipUntilPragmaOpenMPEnd(DKind);
2906 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2907 Loc, Helper.getIdentifiers());
2908 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2909 }
2910 SkipUntil(tok::annot_pragma_openmp_end);
2911 break;
2912 }
2913 case OMPD_allocate: {
2914 // FIXME: Should this be permitted in C++?
2915 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2916 ParsedStmtContext()) {
2917 Diag(Tok, diag::err_omp_immediate_directive)
2918 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2919 }
2920 ConsumeToken();
2921 DeclDirectiveListParserHelper Helper(this, DKind);
2922 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2923 /*AllowScopeSpecifier=*/false)) {
2924 SmallVector<OMPClause *, 1> Clauses;
2925 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2926 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2927 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2928 OpenMPClauseKind CKind =
2929 Tok.isAnnotation() ? OMPC_unknown
2930 : getOpenMPClauseKind(PP.getSpelling(Tok));
2931 Actions.OpenMP().StartOpenMPClause(CKind);
2932 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2933 !SeenClauses[unsigned(CKind)]);
2934 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2936 SeenClauses[unsigned(CKind)] = true;
2937 if (Clause != nullptr)
2938 Clauses.push_back(Clause);
2939 if (Tok.is(tok::annot_pragma_openmp_end)) {
2940 Actions.OpenMP().EndOpenMPClause();
2941 break;
2942 }
2943 // Skip ',' if any.
2944 if (Tok.is(tok::comma))
2945 ConsumeToken();
2946 Actions.OpenMP().EndOpenMPClause();
2947 }
2948 skipUntilPragmaOpenMPEnd(DKind);
2949 }
2950 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
2951 Loc, Helper.getIdentifiers(), Clauses);
2952 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2953 }
2954 SkipUntil(tok::annot_pragma_openmp_end);
2955 break;
2956 }
2957 case OMPD_declare_reduction:
2958 ConsumeToken();
2959 if (DeclGroupPtrTy Res =
2960 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2961 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2963 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2964 } else {
2965 SkipUntil(tok::annot_pragma_openmp_end);
2966 }
2967 break;
2968 case OMPD_declare_mapper: {
2969 ConsumeToken();
2970 if (DeclGroupPtrTy Res =
2971 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2972 // Skip the last annot_pragma_openmp_end.
2973 ConsumeAnnotationToken();
2974 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2975 } else {
2976 SkipUntil(tok::annot_pragma_openmp_end);
2977 }
2978 break;
2979 }
2980 case OMPD_declare_target: {
2981 SourceLocation DTLoc = ConsumeAnyToken();
2982 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2983 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2984 if (HasClauses)
2985 ParseOMPDeclareTargetClauses(DTCI);
2986 bool HasImplicitMappings =
2987 !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2988
2989 if (HasImplicitMappings) {
2990 Diag(Tok, diag::err_omp_unexpected_directive)
2991 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2992 SkipUntil(tok::annot_pragma_openmp_end);
2993 break;
2994 }
2995
2996 // Skip the last annot_pragma_openmp_end.
2998
2999 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
3000 break;
3001 }
3002 case OMPD_begin_declare_variant: {
3003 ConsumeToken();
3005 // Skip the last annot_pragma_openmp_end.
3006 if (!isEofOrEom())
3007 ConsumeAnnotationToken();
3008 }
3009 return Directive;
3010 }
3011 case OMPD_end_declare_variant: {
3012 ConsumeToken();
3013 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
3014 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
3015 else
3016 Diag(Loc, diag::err_expected_begin_declare_variant);
3017 ConsumeAnnotationToken();
3018 break;
3019 }
3020 case OMPD_declare_simd:
3021 case OMPD_begin_declare_target:
3022 case OMPD_end_declare_target:
3023 case OMPD_requires:
3024 case OMPD_declare_variant:
3025 Diag(Tok, diag::err_omp_unexpected_directive)
3026 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
3027 SkipUntil(tok::annot_pragma_openmp_end);
3028 break;
3029 case OMPD_assume: {
3030 ConsumeToken();
3031 Directive = ParseOpenMPInformationalDirective(
3032 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
3033 assert(!Directive.isUnset() &&
3034 "Informational directive remains unprocessed");
3035 return Directive;
3036 }
3037 case OMPD_unknown:
3038 default:
3039 Diag(Tok, diag::err_omp_unknown_directive);
3040 SkipUntil(tok::annot_pragma_openmp_end);
3041 break;
3042 }
3043 return Directive;
3044}
3045
3046bool Parser::ParseOpenMPSimpleVarList(
3048 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
3049 &Callback,
3050 bool AllowScopeSpecifier) {
3051 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
3052 // Parse '('.
3053 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3054 if (T.expectAndConsume(diag::err_expected_lparen_after,
3055 getOpenMPDirectiveName(Kind, OMPVersion).data()))
3056 return true;
3057 bool IsCorrect = true;
3058 bool NoIdentIsFound = true;
3059
3060 // Read tokens while ')' or annot_pragma_openmp_end is not found.
3061 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
3062 CXXScopeSpec SS;
3063 UnqualifiedId Name;
3064 // Read var name.
3065 Token PrevTok = Tok;
3066 NoIdentIsFound = false;
3067
3068 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
3069 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
3070 /*ObjectHasErrors=*/false, false)) {
3071 IsCorrect = false;
3072 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3074 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
3075 /*ObjectHadErrors=*/false, false, false,
3076 false, false, nullptr, Name)) {
3077 IsCorrect = false;
3078 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3080 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
3081 Tok.isNot(tok::annot_pragma_openmp_end)) {
3082 IsCorrect = false;
3083 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3085 Diag(PrevTok.getLocation(), diag::err_expected)
3086 << tok::identifier
3087 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
3088 } else {
3089 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
3090 }
3091 // Consume ','.
3092 if (Tok.is(tok::comma)) {
3093 ConsumeToken();
3094 }
3095 }
3096
3097 if (NoIdentIsFound) {
3098 Diag(Tok, diag::err_expected) << tok::identifier;
3099 IsCorrect = false;
3100 }
3101
3102 // Parse ')'.
3103 IsCorrect = !T.consumeClose() && IsCorrect;
3104
3105 return !IsCorrect;
3106}
3107
3108OMPClause *Parser::ParseOpenMPSizesClause() {
3109 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3110 SmallVector<Expr *, 4> ValExprs;
3111 if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
3112 ValExprs))
3113 return nullptr;
3114
3115 return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
3116 OpenLoc, CloseLoc);
3117}
3118
3119OMPClause *Parser::ParseOpenMPCountsClause() {
3120 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3121 SmallVector<Expr *, 4> ValExprs;
3122 std::optional<unsigned> FillIdx;
3123 unsigned FillCount = 0;
3124 SourceLocation FillLoc;
3125
3126 assert(getOpenMPClauseName(OMPC_counts) == PP.getSpelling(Tok) &&
3127 "Expected parsing to start at clause name");
3128 ClauseNameLoc = ConsumeToken();
3129
3130 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3131 if (T.consumeOpen()) {
3132 Diag(Tok, diag::err_expected) << tok::l_paren;
3133 return nullptr;
3134 }
3135
3136 do {
3137 if (Tok.is(tok::identifier) &&
3138 Tok.getIdentifierInfo()->getName() == "omp_fill") {
3139 if (FillCount == 0)
3140 FillIdx = ValExprs.size();
3141 ++FillCount;
3142 FillLoc = Tok.getLocation();
3143 ConsumeToken();
3144 ValExprs.push_back(nullptr);
3145 } else {
3147 if (!Val.isUsable()) {
3148 T.skipToEnd();
3149 return nullptr;
3150 }
3151 ValExprs.push_back(Val.get());
3152 }
3153 } while (TryConsumeToken(tok::comma));
3154
3155 if (T.consumeClose())
3156 return nullptr;
3157 OpenLoc = T.getOpenLocation();
3158 CloseLoc = T.getCloseLocation();
3159
3160 return Actions.OpenMP().ActOnOpenMPCountsClause(
3161 ValExprs, ClauseNameLoc, OpenLoc, CloseLoc, FillIdx, FillLoc, FillCount);
3162}
3163
3164OMPClause *Parser::ParseOpenMPLoopRangeClause() {
3165 SourceLocation ClauseNameLoc = ConsumeToken();
3166 SourceLocation FirstLoc, CountLoc;
3167
3168 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3169 if (T.consumeOpen()) {
3170 Diag(Tok, diag::err_expected) << tok::l_paren;
3171 return nullptr;
3172 }
3173
3174 FirstLoc = Tok.getLocation();
3176 if (!FirstVal.isUsable()) {
3177 T.skipToEnd();
3178 return nullptr;
3179 }
3180
3181 ExpectAndConsume(tok::comma);
3182
3183 CountLoc = Tok.getLocation();
3185 if (!CountVal.isUsable()) {
3186 T.skipToEnd();
3187 return nullptr;
3188 }
3189
3190 T.consumeClose();
3191
3192 return Actions.OpenMP().ActOnOpenMPLoopRangeClause(
3193 FirstVal.get(), CountVal.get(), ClauseNameLoc, T.getOpenLocation(),
3194 FirstLoc, CountLoc, T.getCloseLocation());
3195}
3196
3197OMPClause *Parser::ParseOpenMPPermutationClause() {
3198 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3199 SmallVector<Expr *> ArgExprs;
3200 if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,
3201 CloseLoc, ArgExprs,
3202 /*ReqIntConst=*/true))
3203 return nullptr;
3204
3205 return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,
3206 OpenLoc, CloseLoc);
3207}
3208
3209OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3210 SourceLocation Loc = Tok.getLocation();
3212
3213 // Parse '('.
3214 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3215 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
3216 return nullptr;
3217 SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
3218 do {
3219 // Parse 'traits(expr) : Allocator' for >=5.2
3220 if (getLangOpts().OpenMP >= 52 && Tok.is(tok::identifier) &&
3221 Tok.getIdentifierInfo()->getName() == "traits") {
3222
3223 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3224
3225 ConsumeToken();
3226
3227 // Parse '(' <expr> ')'
3228 BalancedDelimiterTracker TraitParens(*this, tok::l_paren,
3229 tok::annot_pragma_openmp_end);
3230 TraitParens.consumeOpen();
3231 ExprResult AllocatorTraits =
3232 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3233 TraitParens.consumeClose();
3234
3235 if (AllocatorTraits.isInvalid()) {
3236 SkipUntil(
3237 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3239 break;
3240 }
3241
3242 // Expect ':'
3243 if (Tok.isNot(tok::colon)) {
3244 Diag(Tok, diag::err_expected) << tok::colon;
3245 SkipUntil(
3246 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3248 continue;
3249 }
3250 ConsumeToken();
3251
3252 CXXScopeSpec SS;
3253 ExprResult AllocatorExpr =
3254 getLangOpts().CPlusPlus
3255 ? ParseCXXIdExpression()
3256 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false);
3257
3258 if (AllocatorExpr.isInvalid()) {
3259 SkipUntil(
3260 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3262 break;
3263 }
3264
3265 D.Allocator = AllocatorExpr.get();
3266 D.AllocatorTraits = AllocatorTraits.get();
3267 D.LParenLoc = TraitParens.getOpenLocation();
3268 D.RParenLoc = TraitParens.getCloseLocation();
3269
3270 // Separator handling(;)
3271 if (Tok.is(tok::comma)) {
3272 // In 5.2, comma is invalid
3273 Diag(Tok.getLocation(), diag::err_omp_allocator_comma_separator)
3274 << FixItHint::CreateReplacement(Tok.getLocation(), ";");
3276 } else if (Tok.is(tok::semi)) {
3277 ConsumeAnyToken(); // valid separator
3278 }
3279
3280 continue;
3281 }
3282
3283 // Parse 'Allocator(expr)' for <5.2
3284 CXXScopeSpec SS;
3285 ExprResult Allocator =
3286 getLangOpts().CPlusPlus
3287 ? ParseCXXIdExpression()
3288 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false);
3289 if (Allocator.isInvalid()) {
3290 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3291 StopBeforeMatch);
3292 break;
3293 }
3294 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3295 D.Allocator = Allocator.get();
3296 if (Tok.is(tok::l_paren)) {
3297 BalancedDelimiterTracker T(*this, tok::l_paren,
3298 tok::annot_pragma_openmp_end);
3299 T.consumeOpen();
3300 ExprResult AllocatorTraits =
3301 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3302 T.consumeClose();
3303 if (AllocatorTraits.isInvalid()) {
3304 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3305 StopBeforeMatch);
3306 break;
3307 }
3308 D.AllocatorTraits = AllocatorTraits.get();
3309 D.LParenLoc = T.getOpenLocation();
3310 D.RParenLoc = T.getCloseLocation();
3311
3312 // Deprecation diagnostic in >= 5.2
3313 if (getLangOpts().OpenMP >= 52) {
3314 Diag(Loc, diag::err_omp_deprecate_old_syntax)
3315 << "allocator(expr)" // %0: old form
3316 << "uses_allocators" // %1: clause name
3317 << "traits(expr): alloc"; // %2: suggested new form
3318 }
3319 }
3320 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3321 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
3322 // Parse ','
3323 if (Tok.is(tok::comma))
3324 ConsumeAnyToken();
3325 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
3326 T.consumeClose();
3327 return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3328 Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
3329}
3330
3331OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3332 OpenMPClauseKind CKind, bool FirstClause) {
3333 OMPClauseKind = CKind;
3334 OMPClause *Clause = nullptr;
3335 bool ErrorFound = false;
3336 bool WrongDirective = false;
3337 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
3338
3339 auto CheckClauseValid = [&](OpenMPDirectiveKind D, OpenMPClauseKind C) {
3340 if (!isAllowedClauseForDirective(D, C, OMPVersion)) {
3341 Diag(Tok, diag::err_omp_unexpected_clause)
3342 << getOpenMPClauseName(C) << getOpenMPDirectiveName(D, OMPVersion);
3343 ErrorFound = true;
3344 WrongDirective = true;
3345 }
3346 };
3347
3348 if (CKind != OMPC_unknown) {
3349 // Check if clause is allowed for the given directive.
3350 assert(DKind != OMPD_ordered_blockassoc &&
3351 "Wrong kind for ordered directive");
3352 if (DKind == OMPD_ordered_standalone) {
3353 // Initially OMPD_ordered_standalone is used for ORDERED, before the
3354 // actual kind can be determined.
3355 if (!isAllowedClauseForDirective(DKind, CKind, OMPVersion))
3356 CheckClauseValid(OMPD_ordered_blockassoc, CKind);
3357 } else {
3358 CheckClauseValid(DKind, CKind);
3359 }
3360 }
3361
3362 switch (CKind) {
3363 case OMPC_final:
3364 case OMPC_safelen:
3365 case OMPC_simdlen:
3366 case OMPC_collapse:
3367 case OMPC_ordered:
3368 case OMPC_priority:
3369 case OMPC_grainsize:
3370 case OMPC_num_tasks:
3371 case OMPC_hint:
3372 case OMPC_allocator:
3373 case OMPC_depobj:
3374 case OMPC_detach:
3375 case OMPC_novariants:
3376 case OMPC_nocontext:
3377 case OMPC_filter:
3378 case OMPC_partial:
3379 case OMPC_depth:
3380 case OMPC_align:
3381 case OMPC_message:
3382 case OMPC_ompx_dyn_cgroup_mem:
3383 case OMPC_dyn_groupprivate:
3384 case OMPC_transparent:
3385 // OpenMP [2.5, Restrictions]
3386 // At most one num_threads clause can appear on the directive.
3387 // OpenMP [2.8.1, simd construct, Restrictions]
3388 // Only one safelen clause can appear on a simd directive.
3389 // Only one simdlen clause can appear on a simd directive.
3390 // Only one collapse clause can appear on a simd directive.
3391 // OpenMP [2.11.1, task Construct, Restrictions]
3392 // At most one if clause can appear on the directive.
3393 // At most one final clause can appear on the directive.
3394 // OpenMP [teams Construct, Restrictions]
3395 // At most one num_teams clause can appear on the directive.
3396 // At most one thread_limit clause can appear on the directive.
3397 // OpenMP [2.9.1, task Construct, Restrictions]
3398 // At most one priority clause can appear on the directive.
3399 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3400 // At most one grainsize clause can appear on the directive.
3401 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3402 // At most one num_tasks clause can appear on the directive.
3403 // OpenMP [2.11.3, allocate Directive, Restrictions]
3404 // At most one allocator clause can appear on the directive.
3405 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3406 // At most one detach clause can appear on the directive.
3407 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3408 // At most one novariants clause can appear on a dispatch directive.
3409 // At most one nocontext clause can appear on a dispatch directive.
3410 // OpenMP [5.1, error directive, Restrictions]
3411 // At most one message clause can appear on the directive
3412 if (!FirstClause) {
3413 Diag(Tok, diag::err_omp_more_one_clause)
3414 << getOpenMPDirectiveName(DKind, OMPVersion)
3415 << getOpenMPClauseName(CKind) << 0;
3416 ErrorFound = true;
3417 }
3418
3419 if (CKind == OMPC_transparent && PP.LookAhead(0).isNot(tok::l_paren)) {
3420 SourceLocation Loc = ConsumeToken();
3421 SourceLocation LLoc = Tok.getLocation();
3422 if (!WrongDirective)
3423 Clause = Actions.OpenMP().ActOnOpenMPTransparentClause(nullptr, LLoc,
3424 LLoc, Loc);
3425 break;
3426 }
3427 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3428 PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3429 Clause = ParseOpenMPClause(CKind, WrongDirective);
3430 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
3431 CKind == OMPC_dyn_groupprivate)
3432 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3433 else
3434 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3435 break;
3436 case OMPC_threadset:
3437 case OMPC_fail:
3438 case OMPC_proc_bind:
3439 case OMPC_atomic_default_mem_order:
3440 case OMPC_at:
3441 case OMPC_severity:
3442 case OMPC_bind:
3443 // OpenMP [2.14.3.1, Restrictions]
3444 // Only a single default clause may be specified on a parallel, task or
3445 // teams directive.
3446 // OpenMP [2.5, parallel Construct, Restrictions]
3447 // At most one proc_bind clause can appear on the directive.
3448 // OpenMP [5.0, Requires directive, Restrictions]
3449 // At most one atomic_default_mem_order clause can appear
3450 // on the directive
3451 // OpenMP [5.1, error directive, Restrictions]
3452 // At most one at clause can appear on the directive
3453 // At most one severity clause can appear on the directive
3454 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3455 // At most one bind clause can appear on a loop directive.
3456 if (!FirstClause) {
3457 Diag(Tok, diag::err_omp_more_one_clause)
3458 << getOpenMPDirectiveName(DKind, OMPVersion)
3459 << getOpenMPClauseName(CKind) << 0;
3460 ErrorFound = true;
3461 }
3462
3463 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3464 break;
3465 case OMPC_device:
3466 case OMPC_schedule:
3467 case OMPC_dist_schedule:
3468 case OMPC_defaultmap:
3469 case OMPC_default:
3470 case OMPC_order:
3471 // OpenMP [2.7.1, Restrictions, p. 3]
3472 // Only one schedule clause can appear on a loop directive.
3473 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3474 // At most one defaultmap clause can appear on the directive.
3475 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3476 // At most one device clause can appear on the directive.
3477 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3478 // At most one order clause may appear on a construct.
3479 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3480 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3481 Diag(Tok, diag::err_omp_more_one_clause)
3482 << getOpenMPDirectiveName(DKind, OMPVersion)
3483 << getOpenMPClauseName(CKind) << 0;
3484 ErrorFound = true;
3485 }
3486 [[fallthrough]];
3487 case OMPC_if:
3488 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3489 break;
3490 case OMPC_holds:
3491 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3492 break;
3493 case OMPC_nowait:
3494 case OMPC_untied:
3495 case OMPC_mergeable:
3496 case OMPC_read:
3497 case OMPC_write:
3498 case OMPC_capture:
3499 case OMPC_compare:
3500 case OMPC_seq_cst:
3501 case OMPC_acq_rel:
3502 case OMPC_acquire:
3503 case OMPC_release:
3504 case OMPC_relaxed:
3505 case OMPC_weak:
3506 case OMPC_threads:
3507 case OMPC_simd:
3508 case OMPC_nogroup:
3509 case OMPC_unified_address:
3510 case OMPC_unified_shared_memory:
3511 case OMPC_reverse_offload:
3512 case OMPC_dynamic_allocators:
3513 case OMPC_full:
3514 // OpenMP [2.7.1, Restrictions, p. 9]
3515 // Only one ordered clause can appear on a loop directive.
3516 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3517 // Only one nowait clause can appear on a for directive.
3518 // OpenMP [5.0, Requires directive, Restrictions]
3519 // Each of the requires clauses can appear at most once on the directive.
3520 if (!FirstClause) {
3521 Diag(Tok, diag::err_omp_more_one_clause)
3522 << getOpenMPDirectiveName(DKind, OMPVersion)
3523 << getOpenMPClauseName(CKind) << 0;
3524 ErrorFound = true;
3525 }
3526
3527 if (CKind == OMPC_nowait && PP.LookAhead(/*N=*/0).is(tok::l_paren) &&
3528 getLangOpts().OpenMP >= 60)
3529 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3530 else
3531 Clause = ParseOpenMPClause(CKind, WrongDirective);
3532 break;
3533 case OMPC_self_maps:
3534 // OpenMP [6.0, self_maps clause]
3535 if (getLangOpts().OpenMP < 60) {
3536 Diag(Tok, diag::err_omp_expected_clause)
3537 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
3538 ErrorFound = true;
3539 }
3540 if (!FirstClause) {
3541 Diag(Tok, diag::err_omp_more_one_clause)
3542 << getOpenMPDirectiveName(DKind, OMPVersion)
3543 << getOpenMPClauseName(CKind) << 0;
3544 ErrorFound = true;
3545 }
3546 Clause = ParseOpenMPClause(CKind, WrongDirective);
3547 break;
3548 case OMPC_update:
3549 if (!FirstClause) {
3550 Diag(Tok, diag::err_omp_more_one_clause)
3551 << getOpenMPDirectiveName(DKind, OMPVersion)
3552 << getOpenMPClauseName(CKind) << 0;
3553 ErrorFound = true;
3554 }
3555 Clause = ParseOpenMPClause(CKind, WrongDirective);
3556 break;
3557 case OMPC_update_depend_objects:
3558 if (!FirstClause) {
3559 Diag(Tok, diag::err_omp_more_one_clause)
3560 << getOpenMPDirectiveName(DKind, OMPVersion)
3561 << getOpenMPClauseName(CKind) << 0;
3562 ErrorFound = true;
3563 }
3564
3565 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3566 break;
3567 case OMPC_num_teams:
3568 case OMPC_thread_limit:
3569 case OMPC_num_threads:
3570 if (!FirstClause) {
3571 Diag(Tok, diag::err_omp_more_one_clause)
3572 << getOpenMPDirectiveName(DKind, OMPVersion)
3573 << getOpenMPClauseName(CKind) << 0;
3574 ErrorFound = true;
3575 }
3576 [[fallthrough]];
3577 case OMPC_private:
3578 case OMPC_firstprivate:
3579 case OMPC_lastprivate:
3580 case OMPC_shared:
3581 case OMPC_reduction:
3582 case OMPC_task_reduction:
3583 case OMPC_in_reduction:
3584 case OMPC_linear:
3585 case OMPC_aligned:
3586 case OMPC_copyin:
3587 case OMPC_copyprivate:
3588 case OMPC_flush:
3589 case OMPC_depend:
3590 case OMPC_map:
3591 case OMPC_to:
3592 case OMPC_from:
3593 case OMPC_use_device_ptr:
3594 case OMPC_use_device_addr:
3595 case OMPC_is_device_ptr:
3596 case OMPC_has_device_addr:
3597 case OMPC_allocate:
3598 case OMPC_nontemporal:
3599 case OMPC_inclusive:
3600 case OMPC_exclusive:
3601 case OMPC_affinity:
3602 case OMPC_doacross:
3603 case OMPC_enter:
3604 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered_standalone &&
3605 CKind == OMPC_depend)
3606 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3607 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3608 break;
3609 case OMPC_sizes:
3610 if (!FirstClause) {
3611 Diag(Tok, diag::err_omp_more_one_clause)
3612 << getOpenMPDirectiveName(DKind, OMPVersion)
3613 << getOpenMPClauseName(CKind) << 0;
3614 ErrorFound = true;
3615 }
3616
3617 Clause = ParseOpenMPSizesClause();
3618 break;
3619 case OMPC_permutation:
3620 if (!FirstClause) {
3621 Diag(Tok, diag::err_omp_more_one_clause)
3622 << getOpenMPDirectiveName(DKind, OMPVersion)
3623 << getOpenMPClauseName(CKind) << 0;
3624 ErrorFound = true;
3625 }
3626 Clause = ParseOpenMPPermutationClause();
3627 break;
3628 case OMPC_counts:
3629 if (!FirstClause) {
3630 Diag(Tok, diag::err_omp_more_one_clause)
3631 << getOpenMPDirectiveName(DKind, OMPVersion)
3632 << getOpenMPClauseName(CKind) << 0;
3633 ErrorFound = true;
3634 }
3635 Clause = ParseOpenMPCountsClause();
3636 break;
3637 case OMPC_uses_allocators:
3638 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3639 break;
3640 case OMPC_destroy:
3641 if (DKind != OMPD_interop) {
3642 if (!FirstClause) {
3643 Diag(Tok, diag::err_omp_more_one_clause)
3644 << getOpenMPDirectiveName(DKind, OMPVersion)
3645 << getOpenMPClauseName(CKind) << 0;
3646 ErrorFound = true;
3647 }
3648 Clause = ParseOpenMPClause(CKind, WrongDirective);
3649 break;
3650 }
3651 [[fallthrough]];
3652 case OMPC_init:
3653 case OMPC_use:
3654 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3655 break;
3656 case OMPC_device_type:
3657 case OMPC_unknown:
3658 skipUntilPragmaOpenMPEnd(DKind);
3659 break;
3660 case OMPC_threadprivate:
3661 case OMPC_groupprivate:
3662 case OMPC_uniform:
3663 case OMPC_match:
3664 if (!WrongDirective)
3665 Diag(Tok, diag::err_omp_unexpected_clause)
3666 << getOpenMPClauseName(CKind)
3667 << getOpenMPDirectiveName(DKind, OMPVersion);
3668 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3669 break;
3670 case OMPC_absent:
3671 case OMPC_contains: {
3672 SourceLocation Loc = ConsumeToken();
3673 SourceLocation LLoc = Tok.getLocation();
3674 SourceLocation RLoc;
3675 llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
3676 BalancedDelimiterTracker T(*this, tok::l_paren);
3677 T.consumeOpen();
3678 do {
3679 OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
3680 if (DK == OMPD_unknown) {
3681 skipUntilPragmaOpenMPEnd(OMPD_assume);
3682 Diag(Tok, diag::err_omp_unexpected_clause)
3683 << getOpenMPClauseName(CKind)
3684 << getOpenMPDirectiveName(DKind, OMPVersion);
3685 break;
3686 }
3688 DKVec.push_back(DK);
3689 ConsumeToken();
3690 } else {
3691 Diag(Tok, diag::err_omp_unexpected_clause)
3692 << getOpenMPClauseName(CKind)
3693 << getOpenMPDirectiveName(DKind, OMPVersion);
3694 }
3695 } while (TryConsumeToken(tok::comma));
3696 RLoc = Tok.getLocation();
3697 T.consumeClose();
3698 if (!WrongDirective)
3699 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3700 CKind, DKVec, Loc, LLoc, RLoc);
3701 break;
3702 }
3703 case OMPC_no_openmp:
3704 case OMPC_no_openmp_routines:
3705 case OMPC_no_openmp_constructs:
3706 case OMPC_no_parallelism: {
3707 if (!FirstClause) {
3708 Diag(Tok, diag::err_omp_more_one_clause)
3709 << getOpenMPDirectiveName(DKind, OMPVersion)
3710 << getOpenMPClauseName(CKind) << 0;
3711 ErrorFound = true;
3712 }
3713 SourceLocation Loc = ConsumeToken();
3714 if (!WrongDirective)
3715 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3716 CKind, Loc, Tok.getLocation());
3717 break;
3718 }
3719 case OMPC_ompx_attribute:
3720 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3721 break;
3722 case OMPC_ompx_bare:
3723 if (DKind == llvm::omp::Directive::OMPD_target) {
3724 // Flang splits the combined directives which requires OMPD_target to be
3725 // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
3726 // to explicitly check whether this clause is applied to an `omp target`
3727 // without `teams` and emit an error.
3728 Diag(Tok, diag::err_omp_unexpected_clause)
3729 << getOpenMPClauseName(CKind)
3730 << getOpenMPDirectiveName(DKind, OMPVersion);
3731 ErrorFound = true;
3732 WrongDirective = true;
3733 }
3734 if (WrongDirective)
3735 Diag(Tok, diag::note_ompx_bare_clause)
3736 << getOpenMPClauseName(CKind) << "target teams";
3737 if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3738 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3739 << getOpenMPClauseName(CKind)
3740 << getOpenMPDirectiveName(DKind, OMPVersion);
3741 ErrorFound = true;
3742 }
3743 Clause = ParseOpenMPClause(CKind, WrongDirective);
3744 break;
3745 case OMPC_looprange:
3746 Clause = ParseOpenMPLoopRangeClause();
3747 break;
3748 default:
3749 break;
3750 }
3751 return ErrorFound ? nullptr : Clause;
3752}
3753
3754/// Parses simple expression in parens for single-expression clauses of OpenMP
3755/// constructs.
3756/// \param RLoc Returned location of right paren.
3758 SourceLocation &RLoc,
3759 bool IsAddressOfOperand) {
3760 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3761 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3762 return ExprError();
3763
3764 SourceLocation ELoc = Tok.getLocation();
3765 ExprResult LHS(
3766 ParseCastExpression(CastParseKind::AnyCastExpr, IsAddressOfOperand,
3768 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3769 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3770
3771 // Parse ')'.
3772 RLoc = Tok.getLocation();
3773 if (!T.consumeClose())
3774 RLoc = T.getCloseLocation();
3775
3776 return Val;
3777}
3778
3779OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3780 bool ParseOnly) {
3782 SourceLocation LLoc = Tok.getLocation();
3783 SourceLocation RLoc;
3784
3785 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3786
3787 if (Val.isInvalid())
3788 return nullptr;
3789
3790 if (ParseOnly)
3791 return nullptr;
3792 return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3793 LLoc, RLoc);
3794}
3795
3796bool Parser::ParseOpenMPIndirectClause(
3797 SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3799 SourceLocation RLoc;
3800
3801 if (Tok.isNot(tok::l_paren)) {
3802 if (ParseOnly)
3803 return false;
3804 DTCI.Indirect = nullptr;
3805 return true;
3806 }
3807
3808 ExprResult Val =
3809 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3810 if (Val.isInvalid())
3811 return false;
3812
3813 if (ParseOnly)
3814 return false;
3815
3816 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3817 !Val.get()->isInstantiationDependent() &&
3819 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3820 if (Ret.isInvalid())
3821 return false;
3822 llvm::APSInt Result;
3823 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3825 if (Ret.isInvalid())
3826 return false;
3827 DTCI.Indirect = Val.get();
3828 return true;
3829 }
3830 return false;
3831}
3832
3833ExprResult Parser::ParseOMPInteropFrSelector() {
3834 ConsumeToken(); // 'fr'
3835 BalancedDelimiterTracker FT(*this, tok::l_paren,
3836 tok::annot_pragma_openmp_end);
3837 if (FT.expectAndConsume(diag::err_expected_lparen_after, "fr")) {
3838 SkipUntil(
3839 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3841 return ExprError();
3842 }
3843 SourceLocation Loc = Tok.getLocation();
3844 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3845 ExprResult Arg = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3846 Arg = Actions.ActOnFinishFullExpr(Arg.get(), Loc, /*DiscardedValue=*/false);
3847 FT.consumeClose();
3848 return Arg;
3849}
3850
3851bool Parser::ParseOMPInteropAttrSelector(SmallVectorImpl<Expr *> &Attrs) {
3852 ConsumeToken(); // 'attr'
3853 BalancedDelimiterTracker AT(*this, tok::l_paren,
3854 tok::annot_pragma_openmp_end);
3855 if (AT.expectAndConsume(diag::err_expected_lparen_after, "attr")) {
3856 SkipUntil(
3857 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3859 return true;
3860 }
3861 bool HasError = false;
3862 // attr() requires at least one ext-string-literal argument; an empty list is
3863 // not permitted by the prefer_type grammar.
3864 if (Tok.is(tok::r_paren)) {
3865 Diag(Tok, diag::err_omp_interop_attr_not_string);
3866 HasError = true;
3867 }
3868 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::r_brace) &&
3869 Tok.isNot(tok::annot_pragma_openmp_end)) {
3870 if (Tok.is(tok::string_literal)) {
3872 if (S.isUsable())
3873 Attrs.push_back(S.get());
3874 else
3875 HasError = true;
3876 } else {
3877 HasError = true;
3878 Diag(Tok, diag::err_omp_interop_attr_not_string);
3879 ConsumeToken();
3880 }
3881 if (Tok.is(tok::comma))
3882 ConsumeToken();
3883 }
3884 AT.consumeClose();
3885 return HasError;
3886}
3887
3888bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3889 OpenMPClauseKind Kind) {
3890 const Token &Tok = getCurToken();
3891 bool HasError = false;
3892 bool IsTarget = false;
3893 bool IsTargetSync = false;
3894
3895 while (Tok.is(tok::identifier)) {
3896 // prefer_type is allowed with 'init' and 'append_args' and must be first.
3897 bool PreferTypeAllowed = (Kind == OMPC_init || Kind == OMPC_append_args) &&
3898 InteropInfo.Prefs.empty() && !IsTarget &&
3899 !IsTargetSync;
3900 if (Tok.getIdentifierInfo()->isStr("target")) {
3901 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3902 // Each interop-type may be specified on an action-clause at most
3903 // once.
3904 if (IsTarget)
3905 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3906 IsTarget = true;
3907 ConsumeToken();
3908 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3909 if (IsTargetSync)
3910 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3911 IsTargetSync = true;
3912 ConsumeToken();
3913 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3914 PreferTypeAllowed) {
3915 if (Kind == OMPC_append_args && getLangOpts().OpenMP < 60) {
3916 Diag(Tok, diag::err_omp_append_args_prefer_type_60);
3917 HasError = true;
3918 }
3919 ConsumeToken();
3920 BalancedDelimiterTracker PT(*this, tok::l_paren,
3921 tok::annot_pragma_openmp_end);
3922 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3923 HasError = true;
3924
3925 // prefer_type requires at least one preference-specification.
3926 if (Tok.is(tok::r_paren)) {
3927 Diag(Tok, diag::err_omp_expected_pref_spec);
3928 HasError = true;
3929 }
3930
3931 while (Tok.isNot(tok::r_paren) &&
3932 Tok.isNot(tok::annot_pragma_openmp_end)) {
3933 // OMP 6.0: { fr(...), attr(...) } brace-grouped pref-spec
3934 if (Tok.is(tok::l_brace)) {
3935 // The brace-grouped form was introduced in OpenMP 6.0; earlier
3936 // versions only allow the flat foreign-runtime-id list.
3937 if (getLangOpts().OpenMP < 60) {
3938 Diag(Tok, diag::err_omp_prefer_type_brace_60);
3939 HasError = true;
3940 }
3941 BalancedDelimiterTracker BT(*this, tok::l_brace,
3942 tok::annot_pragma_openmp_end);
3943 BT.consumeOpen();
3944 Expr *FrExpr = nullptr;
3945 SmallVector<Expr *, 2> AttrExprs;
3946 bool SeenFr = false;
3947
3948 // A pref-spec requires at least one 'fr'/'attr' selector; {} is not
3949 // permitted by the grammar.
3950 if (Tok.is(tok::r_brace)) {
3951 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3952 HasError = true;
3953 }
3954
3955 while (Tok.isNot(tok::r_brace) &&
3956 Tok.isNot(tok::annot_pragma_openmp_end)) {
3957 if (Tok.is(tok::identifier) &&
3958 Tok.getIdentifierInfo()->isStr("fr")) {
3959 if (SeenFr) {
3960 Diag(Tok, diag::err_omp_interop_multiple_fr);
3961 HasError = true;
3962 ConsumeToken(); // 'fr'
3963 SkipUntil(
3964 {tok::comma, tok::r_brace, tok::annot_pragma_openmp_end},
3966 continue;
3967 }
3968 SeenFr = true;
3969 ExprResult Fr = ParseOMPInteropFrSelector();
3970 if (Fr.isUsable())
3971 FrExpr = Fr.get();
3972 else
3973 HasError = true;
3974 } else if (Tok.is(tok::identifier) &&
3975 Tok.getIdentifierInfo()->isStr("attr")) {
3976 if (ParseOMPInteropAttrSelector(AttrExprs))
3977 HasError = true;
3978 } else {
3979 // Neither 'fr' nor 'attr' (a non-identifier or some other word).
3980 HasError = true;
3981 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3982 ConsumeToken();
3983 }
3984 if (Tok.is(tok::comma))
3985 ConsumeToken();
3986 }
3987 if (BT.consumeClose())
3988 HasError = true;
3989
3990 if (FrExpr || !AttrExprs.empty())
3991 InteropInfo.Prefs.emplace_back(FrExpr, AttrExprs);
3992 InteropInfo.HasPreferAttrs = true;
3993 } else {
3994 // OMP 5.1: flat foreign-runtime-id (string or int). Stored as a
3995 // pref-spec with Fr=expr and no attr() entries.
3996 SourceLocation Loc = Tok.getLocation();
3997 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3998 ExprResult PTExpr =
3999 ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4000 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
4001 /*DiscardedValue=*/false);
4002 if (PTExpr.isUsable()) {
4003 InteropInfo.Prefs.emplace_back(PTExpr.get(),
4004 llvm::SmallVector<Expr *, 2>{});
4005 } else {
4006 HasError = true;
4007 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4009 }
4010 }
4011
4012 if (Tok.is(tok::comma))
4013 ConsumeToken();
4014 }
4015 PT.consumeClose();
4016 } else {
4017 HasError = true;
4018 Diag(Tok, diag::err_omp_expected_interop_type);
4019 ConsumeToken();
4020 }
4021 if (!Tok.is(tok::comma))
4022 break;
4023 ConsumeToken();
4024 }
4025
4026 if (!HasError && !IsTarget && !IsTargetSync) {
4027 Diag(Tok, diag::err_omp_expected_interop_type);
4028 HasError = true;
4029 }
4030
4031 if (Kind == OMPC_init) {
4032 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
4033 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
4034 if (Tok.is(tok::colon))
4035 ConsumeToken();
4036 }
4037
4038 // As of OpenMP 5.1,there are two interop-types, "target" and
4039 // "targetsync". Either or both are allowed for a single interop.
4040 InteropInfo.IsTarget = IsTarget;
4041 InteropInfo.IsTargetSync = IsTargetSync;
4042
4043 return HasError;
4044}
4045
4046OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
4047 bool ParseOnly) {
4048 SourceLocation Loc = ConsumeToken();
4049 // Parse '('.
4050 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4051 if (T.expectAndConsume(diag::err_expected_lparen_after,
4052 getOpenMPClauseName(Kind).data()))
4053 return nullptr;
4054
4055 bool InteropError = false;
4056 OMPInteropInfo InteropInfo;
4057 if (Kind == OMPC_init)
4058 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
4059
4060 // Parse the variable.
4061 SourceLocation VarLoc = Tok.getLocation();
4062 ExprResult InteropVarExpr = ParseAssignmentExpression();
4063 if (!InteropVarExpr.isUsable()) {
4064 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4066 }
4067
4068 // Parse ')'.
4069 SourceLocation RLoc = Tok.getLocation();
4070 if (!T.consumeClose())
4071 RLoc = T.getCloseLocation();
4072
4073 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
4074 return nullptr;
4075
4076 if (Kind == OMPC_init)
4077 return Actions.OpenMP().ActOnOpenMPInitClause(
4078 InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
4079 RLoc);
4080 if (Kind == OMPC_use)
4081 return Actions.OpenMP().ActOnOpenMPUseClause(
4082 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
4083
4084 if (Kind == OMPC_destroy)
4085 return Actions.OpenMP().ActOnOpenMPDestroyClause(
4086 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
4087
4088 llvm_unreachable("Unexpected interop variable clause.");
4089}
4090
4091OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
4092 SourceLocation Loc = ConsumeToken();
4093 // Parse '('.
4094 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4095 if (T.expectAndConsume(diag::err_expected_lparen_after,
4096 getOpenMPClauseName(OMPC_ompx_attribute).data()))
4097 return nullptr;
4098
4099 ParsedAttributes ParsedAttrs(AttrFactory);
4100 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
4101
4102 // Parse ')'.
4103 if (T.consumeClose())
4104 return nullptr;
4105
4106 if (ParseOnly)
4107 return nullptr;
4108
4109 SmallVector<Attr *> Attrs;
4110 for (const ParsedAttr &PA : ParsedAttrs) {
4111 switch (PA.getKind()) {
4112 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
4113 if (!PA.checkExactlyNumArgs(Actions, 2))
4114 continue;
4115 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
4116 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
4117 Attrs.push_back(A);
4118 continue;
4119 case ParsedAttr::AT_AMDGPUWavesPerEU:
4120 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
4121 !PA.checkAtMostNumArgs(Actions, 2))
4122 continue;
4123 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
4124 PA, PA.getArgAsExpr(0),
4125 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
4126 Attrs.push_back(A);
4127 continue;
4128 case ParsedAttr::AT_CUDALaunchBounds:
4129 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
4130 !PA.checkAtMostNumArgs(Actions, 3))
4131 continue;
4132 if (auto *A = Actions.CreateLaunchBoundsAttr(
4133 PA, PA.getArgAsExpr(0),
4134 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
4135 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr,
4136 /*IgnoreArch=*/true))
4137 Attrs.push_back(A);
4138 continue;
4139 default:
4140 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
4141 continue;
4142 };
4143 }
4144
4145 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
4146 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
4147}
4148
4149OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
4150 bool ParseOnly) {
4151 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
4152 if (!Val || ParseOnly)
4153 return nullptr;
4154 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
4155 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
4156 static_cast<DefaultKind>(Val->Type) ==
4157 OMP_DEFAULT_firstprivate)) {
4158 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
4159 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
4160 OMP_DEFAULT_private
4161 ? OMPC_private
4162 : OMPC_firstprivate)
4163 << getOpenMPClauseName(OMPC_default) << "5.1";
4164 return nullptr;
4165 }
4166 return Actions.OpenMP().ActOnOpenMPSimpleClause(
4167 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
4168}
4169
4170OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
4171 SourceLocation Loc = Tok.getLocation();
4173
4174 if (ParseOnly)
4175 return nullptr;
4176 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
4177}
4178
4179OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
4180 OpenMPClauseKind Kind,
4181 bool ParseOnly) {
4182 SourceLocation Loc = ConsumeToken();
4183 SourceLocation DelimLoc;
4184 // Parse '('.
4185 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4186 if (T.expectAndConsume(diag::err_expected_lparen_after,
4187 getOpenMPClauseName(Kind).data()))
4188 return nullptr;
4189
4190 ExprResult Val;
4191 SmallVector<unsigned, 4> Arg;
4192 SmallVector<SourceLocation, 4> KLoc;
4193 if (Kind == OMPC_schedule) {
4194 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
4195 Arg.resize(NumberOfElements);
4196 KLoc.resize(NumberOfElements);
4197 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
4198 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
4199 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
4200 unsigned KindModifier = getOpenMPSimpleClauseType(
4201 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4202 if (KindModifier > OMPC_SCHEDULE_unknown) {
4203 // Parse 'modifier'
4204 Arg[Modifier1] = KindModifier;
4205 KLoc[Modifier1] = Tok.getLocation();
4206 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4207 Tok.isNot(tok::annot_pragma_openmp_end))
4209 if (Tok.is(tok::comma)) {
4210 // Parse ',' 'modifier'
4212 KindModifier = getOpenMPSimpleClauseType(
4213 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4214 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
4215 ? KindModifier
4216 : (unsigned)OMPC_SCHEDULE_unknown;
4217 KLoc[Modifier2] = Tok.getLocation();
4218 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4219 Tok.isNot(tok::annot_pragma_openmp_end))
4221 }
4222 // Parse ':'
4223 if (Tok.is(tok::colon))
4225 else
4226 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
4227 KindModifier = getOpenMPSimpleClauseType(
4228 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4229 }
4230 Arg[ScheduleKind] = KindModifier;
4231 KLoc[ScheduleKind] = Tok.getLocation();
4232 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4233 Tok.isNot(tok::annot_pragma_openmp_end))
4235 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
4236 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
4237 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
4238 Tok.is(tok::comma))
4239 DelimLoc = ConsumeAnyToken();
4240 } else if (Kind == OMPC_dist_schedule) {
4241 Arg.push_back(getOpenMPSimpleClauseType(
4242 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4243 KLoc.push_back(Tok.getLocation());
4244 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4245 Tok.isNot(tok::annot_pragma_openmp_end))
4247 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
4248 DelimLoc = ConsumeAnyToken();
4249 } else if (Kind == OMPC_default) {
4250 // Get a default modifier
4251 unsigned Modifier = getOpenMPSimpleClauseType(
4252 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4253
4254 Arg.push_back(Modifier);
4255 KLoc.push_back(Tok.getLocation());
4256 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4257 Tok.isNot(tok::annot_pragma_openmp_end))
4259 // Parse ':'
4260 if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {
4262 // Get a variable-category attribute for default clause modifier
4263 OpenMPDefaultClauseVariableCategory VariableCategory =
4265 Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4266 Arg.push_back(VariableCategory);
4267 KLoc.push_back(Tok.getLocation());
4268 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4269 Tok.isNot(tok::annot_pragma_openmp_end))
4271 } else {
4272 Arg.push_back(OMPC_DEFAULT_VC_all);
4273 KLoc.push_back(SourceLocation());
4274 }
4275 } else if (Kind == OMPC_defaultmap) {
4276 // Get a defaultmap modifier
4277 unsigned Modifier = getOpenMPSimpleClauseType(
4278 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4279
4280 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
4281 // pointer
4282 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
4284 Arg.push_back(Modifier);
4285 KLoc.push_back(Tok.getLocation());
4286 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4287 Tok.isNot(tok::annot_pragma_openmp_end))
4289 // Parse ':'
4290 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
4291 if (Tok.is(tok::colon))
4293 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
4294 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
4295 // Get a defaultmap kind
4296 Arg.push_back(getOpenMPSimpleClauseType(
4297 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4298 KLoc.push_back(Tok.getLocation());
4299 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4300 Tok.isNot(tok::annot_pragma_openmp_end))
4302 } else {
4303 Arg.push_back(OMPC_DEFAULTMAP_unknown);
4304 KLoc.push_back(SourceLocation());
4305 }
4306 } else if (Kind == OMPC_order) {
4307 enum { Modifier, OrderKind, NumberOfElements };
4308 Arg.resize(NumberOfElements);
4309 KLoc.resize(NumberOfElements);
4310 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
4311 Arg[OrderKind] = OMPC_ORDER_unknown;
4312 unsigned KindModifier = getOpenMPSimpleClauseType(
4313 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4314 if (KindModifier > OMPC_ORDER_unknown) {
4315 // Parse 'modifier'
4316 Arg[Modifier] = KindModifier;
4317 KLoc[Modifier] = Tok.getLocation();
4318 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4319 Tok.isNot(tok::annot_pragma_openmp_end))
4321 // Parse ':'
4322 if (Tok.is(tok::colon))
4324 else
4325 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
4326 KindModifier = getOpenMPSimpleClauseType(
4327 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4328 }
4329 Arg[OrderKind] = KindModifier;
4330 KLoc[OrderKind] = Tok.getLocation();
4331 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4332 Tok.isNot(tok::annot_pragma_openmp_end))
4334 } else if (Kind == OMPC_device) {
4335 // Only target executable directives support extended device construct.
4336 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4337 NextToken().is(tok::colon)) {
4338 // Parse optional <device modifier> ':'
4339 Arg.push_back(getOpenMPSimpleClauseType(
4340 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4341 KLoc.push_back(Tok.getLocation());
4343 // Parse ':'
4345 } else {
4346 Arg.push_back(OMPC_DEVICE_unknown);
4347 KLoc.emplace_back();
4348 }
4349 } else if (Kind == OMPC_grainsize) {
4350 // Parse optional <grainsize modifier> ':'
4353 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4354 getLangOpts()));
4355 if (getLangOpts().OpenMP >= 51) {
4356 if (NextToken().is(tok::colon)) {
4357 Arg.push_back(Modifier);
4358 KLoc.push_back(Tok.getLocation());
4359 // Parse modifier
4361 // Parse ':'
4363 } else {
4364 if (Modifier == OMPC_GRAINSIZE_strict) {
4365 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4366 // Parse modifier
4368 }
4369 Arg.push_back(OMPC_GRAINSIZE_unknown);
4370 KLoc.emplace_back();
4371 }
4372 } else {
4373 Arg.push_back(OMPC_GRAINSIZE_unknown);
4374 KLoc.emplace_back();
4375 }
4376 } else if (Kind == OMPC_dyn_groupprivate) {
4377 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
4378 Arg.resize(NumberOfModifiers);
4379 KLoc.resize(NumberOfModifiers);
4380 Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
4381 Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
4382
4383 auto ConsumeModifier = [&]() {
4384 unsigned Type = NumberOfModifiers;
4385 unsigned Modifier;
4386 SourceLocation Loc;
4387 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
4388 NextToken().is(tok::l_paren)) {
4389 ConsumeToken();
4390 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4391 ParenT.consumeOpen();
4392
4393 Modifier = getOpenMPSimpleClauseType(
4394 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4397 Diag(Tok.getLocation(), diag::err_expected)
4398 << "'abort', 'null' or 'default_mem' in fallback modifier";
4399 SkipUntil(tok::r_paren);
4400 return std::make_tuple(Type, Modifier, Loc);
4401 }
4402 Type = ComplexModifier;
4403 Loc = Tok.getLocation();
4404 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4405 Tok.isNot(tok::annot_pragma_openmp_end))
4407 ParenT.consumeClose();
4408 } else {
4409 Modifier = getOpenMPSimpleClauseType(
4410 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4411 if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
4412 Type = SimpleModifier;
4413 Loc = Tok.getLocation();
4414 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4415 Tok.isNot(tok::annot_pragma_openmp_end))
4417 }
4418 }
4419 return std::make_tuple(Type, Modifier, Loc);
4420 };
4421
4422 auto SaveModifier = [&](unsigned Type, unsigned Modifier,
4423 SourceLocation Loc) {
4424 assert(Type < NumberOfModifiers && "Unexpected modifier type");
4425 if (!KLoc[Type].isValid()) {
4426 Arg[Type] = Modifier;
4427 KLoc[Type] = Loc;
4428 } else {
4429 Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
4430 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
4431 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
4432 }
4433 };
4434
4435 // Parse 'modifier'
4436 auto [Type1, Mod1, Loc1] = ConsumeModifier();
4437 if (Type1 < NumberOfModifiers) {
4438 SaveModifier(Type1, Mod1, Loc1);
4439 if (Tok.is(tok::comma)) {
4440 // Parse ',' 'modifier'
4442 auto [Type2, Mod2, Loc2] = ConsumeModifier();
4443 if (Type2 < NumberOfModifiers)
4444 SaveModifier(Type2, Mod2, Loc2);
4445 }
4446 // Parse ':'
4447 if (Tok.is(tok::colon))
4449 else
4450 Diag(Tok, diag::warn_pragma_expected_colon)
4451 << "dyn_groupprivate modifier";
4452 }
4453 } else if (Kind == OMPC_num_tasks) {
4454 // Parse optional <num_tasks modifier> ':'
4457 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4458 getLangOpts()));
4459 if (getLangOpts().OpenMP >= 51) {
4460 if (NextToken().is(tok::colon)) {
4461 Arg.push_back(Modifier);
4462 KLoc.push_back(Tok.getLocation());
4463 // Parse modifier
4465 // Parse ':'
4467 } else {
4468 if (Modifier == OMPC_NUMTASKS_strict) {
4469 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4470 // Parse modifier
4472 }
4473 Arg.push_back(OMPC_NUMTASKS_unknown);
4474 KLoc.emplace_back();
4475 }
4476 } else {
4477 Arg.push_back(OMPC_NUMTASKS_unknown);
4478 KLoc.emplace_back();
4479 }
4480 } else {
4481 assert(Kind == OMPC_if);
4482 KLoc.push_back(Tok.getLocation());
4483 TentativeParsingAction TPA(*this);
4484 auto DK = parseOpenMPDirectiveKind(*this);
4485 Arg.push_back(static_cast<unsigned>(DK));
4486 if (DK != OMPD_unknown) {
4487 ConsumeToken();
4488 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4489 TPA.Commit();
4490 DelimLoc = ConsumeToken();
4491 } else {
4492 TPA.Revert();
4493 Arg.back() = unsigned(OMPD_unknown);
4494 }
4495 } else {
4496 TPA.Revert();
4497 }
4498 }
4499
4500 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4501 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
4502 Kind == OMPC_if || Kind == OMPC_device ||
4503 Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
4504 Kind == OMPC_dyn_groupprivate;
4505 if (NeedAnExpression) {
4506 SourceLocation ELoc = Tok.getLocation();
4507 ExprResult LHS(
4508 ParseCastExpression(CastParseKind::AnyCastExpr, false,
4510 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4511 Val =
4512 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4513 }
4514
4515 // Parse ')'.
4516 SourceLocation RLoc = Tok.getLocation();
4517 if (!T.consumeClose())
4518 RLoc = T.getCloseLocation();
4519
4520 if (NeedAnExpression && Val.isInvalid())
4521 return nullptr;
4522
4523 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
4524 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
4525 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
4526 Diag(KLoc[0], diag::err_omp_invalid_dsa)
4527 << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==
4528 OMP_DEFAULT_private
4529 ? OMPC_private
4530 : OMPC_firstprivate)
4531 << getOpenMPClauseName(OMPC_default) << "5.1";
4532 return nullptr;
4533 }
4534
4535 if (ParseOnly)
4536 return nullptr;
4537 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4538 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4539}
4540
4541static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4542 UnqualifiedId &ReductionId) {
4543 if (ReductionIdScopeSpec.isEmpty()) {
4544 auto OOK = OO_None;
4545 switch (P.getCurToken().getKind()) {
4546 case tok::plus:
4547 OOK = OO_Plus;
4548 break;
4549 case tok::minus:
4550 OOK = OO_Minus;
4551 break;
4552 case tok::star:
4553 OOK = OO_Star;
4554 break;
4555 case tok::amp:
4556 OOK = OO_Amp;
4557 break;
4558 case tok::pipe:
4559 OOK = OO_Pipe;
4560 break;
4561 case tok::caret:
4562 OOK = OO_Caret;
4563 break;
4564 case tok::ampamp:
4565 OOK = OO_AmpAmp;
4566 break;
4567 case tok::pipepipe:
4568 OOK = OO_PipePipe;
4569 break;
4570 default:
4571 break;
4572 }
4573 if (OOK != OO_None) {
4574 SourceLocation OpLoc = P.ConsumeToken();
4575 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4576 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4577 return false;
4578 }
4579 }
4580 return P.ParseUnqualifiedId(
4581 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4582 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4583 /*AllowDestructorName*/ false,
4584 /*AllowConstructorName*/ false,
4585 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4586}
4587
4588/// Checks if the token is a valid map-type-modifier.
4589/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4591 Token Tok = P.getCurToken();
4592 if (!Tok.is(tok::identifier))
4594
4595 Preprocessor &PP = P.getPreprocessor();
4596 OpenMPMapModifierKind TypeModifier =
4598 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4599 return TypeModifier;
4600}
4601
4603 // Parse '('.
4604 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4605 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4606 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4608 return true;
4609 }
4610 // Parse mapper-identifier
4611 if (getLangOpts().CPlusPlus)
4612 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4613 /*ObjectType=*/nullptr,
4614 /*ObjectHasErrors=*/false,
4615 /*EnteringContext=*/false);
4616 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4617 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4618 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4620 return true;
4621 }
4622 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4623 Data.ReductionOrMapperId = DeclarationNameInfo(
4624 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4625 ConsumeToken();
4626 // Parse ')'.
4627 return T.consumeClose();
4628}
4629
4631
4633 bool HasMapType = false;
4634 SourceLocation PreMapLoc = Tok.getLocation();
4635 StringRef PreMapName = "";
4636 while (getCurToken().isNot(tok::colon)) {
4637 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4638 OpenMPMapClauseKind MapKind = isMapType(*this);
4639 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4640 TypeModifier == OMPC_MAP_MODIFIER_close ||
4641 TypeModifier == OMPC_MAP_MODIFIER_present ||
4642 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4643 Data.MapTypeModifiers.push_back(TypeModifier);
4644 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4645 if (PP.LookAhead(0).isNot(tok::comma) &&
4646 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4647 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4648 << "map type modifier";
4649 ConsumeToken();
4650 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4651 Data.MapTypeModifiers.push_back(TypeModifier);
4652 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4653 ConsumeToken();
4655 return true;
4656 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4657 getLangOpts().OpenMP >= 52)
4658 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4659 << "map type modifier";
4660
4661 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4662 if (!HasMapType) {
4663 HasMapType = true;
4664 Data.ExtraModifier = MapKind;
4665 MapKind = OMPC_MAP_unknown;
4666 PreMapLoc = Tok.getLocation();
4667 PreMapName = Tok.getIdentifierInfo()->getName();
4668 } else {
4669 Diag(Tok, diag::err_omp_more_one_map_type);
4670 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4671 << PreMapName;
4672 }
4673 ConsumeToken();
4674 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
4675 Data.MapTypeModifiers.push_back(TypeModifier);
4676 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4677 if (PP.LookAhead(0).isNot(tok::comma) &&
4678 PP.LookAhead(0).isNot(tok::colon))
4679 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4680 << "map type modifier";
4681 if (getLangOpts().OpenMP < 60)
4682 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4683 << (getLangOpts().OpenMP >= 51
4684 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4685 : 0)
4686 << getLangOpts().OpenMPExtensions << 0;
4687 ConsumeToken();
4688 } else {
4689 // For the case of unknown map-type-modifier or a map-type.
4690 // Map-type is followed by a colon; the function returns when it
4691 // encounters a token followed by a colon.
4692 if (Tok.is(tok::comma)) {
4693 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4694 ConsumeToken();
4695 continue;
4696 }
4697 // Potential map-type token as it is followed by a colon.
4698 if (PP.LookAhead(0).is(tok::colon)) {
4699 if (getLangOpts().OpenMP >= 60) {
4700 break;
4701 } else {
4702 return false;
4703 }
4704 }
4705
4706 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4707 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4708 : 0)
4709 << getLangOpts().OpenMPExtensions
4710 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
4711 ConsumeToken();
4712 }
4713 if (getCurToken().is(tok::comma))
4714 ConsumeToken();
4715 }
4716 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4717 if (!Tok.is(tok::colon)) {
4718 Diag(Tok, diag::err_omp_unknown_map_type);
4719 ConsumeToken();
4720 } else {
4721 Data.ExtraModifier = OMPC_MAP_unknown;
4722 }
4723 }
4724 return false;
4725}
4726
4727/// Checks if the token is a valid map-type.
4728/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4730 Token Tok = P.getCurToken();
4731 // The map-type token can be either an identifier or the C++ delete keyword.
4732 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4733 return OMPC_MAP_unknown;
4734 Preprocessor &PP = P.getPreprocessor();
4735 unsigned MapType =
4737 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4738 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4739 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4740 return static_cast<OpenMPMapClauseKind>(MapType);
4741 return OMPC_MAP_unknown;
4742}
4743
4744/// Parse map-type in map clause.
4745/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4746/// where, map-type ::= to | from | tofrom | alloc | release | delete
4748 Token Tok = P.getCurToken();
4749 if (Tok.is(tok::colon)) {
4750 P.Diag(Tok, diag::err_omp_map_type_missing);
4751 return;
4752 }
4753 Data.ExtraModifier = isMapType(P);
4754 if (Data.ExtraModifier == OMPC_MAP_unknown)
4755 P.Diag(Tok, diag::err_omp_unknown_map_type);
4756 P.ConsumeToken();
4757}
4758
4759ExprResult Parser::ParseOpenMPIteratorsExpr() {
4760 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4761 "Expected 'iterator' token.");
4762 SourceLocation IteratorKwLoc = ConsumeToken();
4763
4764 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4765 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4766 return ExprError();
4767
4768 SourceLocation LLoc = T.getOpenLocation();
4769 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4770 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4771 // Check if the type parsing is required.
4772 ParsedType IteratorType;
4773 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4774 // identifier '=' is not found - parse type.
4776 if (TR.isInvalid()) {
4777 T.skipToEnd();
4778 return ExprError();
4779 }
4780 IteratorType = TR.get();
4781 }
4782
4783 // Parse identifier.
4784 IdentifierInfo *II = nullptr;
4785 SourceLocation IdLoc;
4786 if (Tok.is(tok::identifier)) {
4787 II = Tok.getIdentifierInfo();
4788 IdLoc = ConsumeToken();
4789 } else {
4790 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4791 }
4792
4793 // Parse '='.
4794 SourceLocation AssignLoc;
4795 if (Tok.is(tok::equal))
4796 AssignLoc = ConsumeToken();
4797 else
4798 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4799
4800 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4801 ColonProtectionRAIIObject ColonRAII(*this);
4802 // Parse <begin>
4803 SourceLocation Loc = Tok.getLocation();
4804 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4805 ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4806 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4807 /*DiscardedValue=*/false);
4808 // Parse ':'.
4809 SourceLocation ColonLoc;
4810 if (Tok.is(tok::colon))
4811 ColonLoc = ConsumeToken();
4812
4813 // Parse <end>
4814 Loc = Tok.getLocation();
4815 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4816 ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4817 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4818 /*DiscardedValue=*/false);
4819
4820 SourceLocation SecColonLoc;
4821 ExprResult Step;
4822 // Parse optional step.
4823 if (Tok.is(tok::colon)) {
4824 // Parse ':'
4825 SecColonLoc = ConsumeToken();
4826 // Parse <step>
4827 Loc = Tok.getLocation();
4828 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4829 Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4830 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4831 /*DiscardedValue=*/false);
4832 }
4833
4834 // Parse ',' or ')'
4835 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4836 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4837 if (Tok.is(tok::comma))
4838 ConsumeToken();
4839
4840 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4841 D.DeclIdent = II;
4842 D.DeclIdentLoc = IdLoc;
4843 D.Type = IteratorType;
4844 D.AssignLoc = AssignLoc;
4845 D.ColonLoc = ColonLoc;
4846 D.SecColonLoc = SecColonLoc;
4847 D.Range.Begin = Begin.get();
4848 D.Range.End = End.get();
4849 D.Range.Step = Step.get();
4850 }
4851
4852 // Parse ')'.
4853 SourceLocation RLoc = Tok.getLocation();
4854 if (!T.consumeClose())
4855 RLoc = T.getCloseLocation();
4856
4857 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4858 LLoc, RLoc, Data);
4859}
4860
4863 const LangOptions &LangOpts) {
4864 // Currently the only reserved locator is 'omp_all_memory' which is only
4865 // allowed on a depend clause.
4866 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4867 return false;
4868
4869 if (Tok.is(tok::identifier) &&
4870 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4871
4872 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4873 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4874 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4875 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4876 Data.ExtraModifier != OMPC_DEPEND_inout)
4877 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4878 else
4879 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4880 ? OMPC_DEPEND_outallmemory
4881 : OMPC_DEPEND_inoutallmemory;
4882 ConsumeToken();
4883 return true;
4884 }
4885 return false;
4886}
4887
4889 // 'omp_num_args' is recognised by spelling: OpenMP 6.0 [5.2.1] gives it no
4890 // declaration, so it is never looked up.
4891 if (Tok.isNot(tok::identifier) ||
4892 !Tok.getIdentifierInfo()->isStr("omp_num_args")) {
4894 if (E.isInvalid())
4895 return true;
4896 E = Actions.ActOnFinishFullExpr(E.get(), E.get()->getExprLoc(),
4897 /*DiscardedValue=*/false);
4898 if (E.isInvalid())
4899 return true;
4901 Bound.E = E.get();
4902 return false;
4903 }
4904
4906 ConsumeToken();
4907 if (Tok.isOneOf(tok::plus, tok::minus)) {
4908 Bound.IsSubtraction = Tok.is(tok::minus);
4909 ConsumeToken();
4910 // OpenMP 6.0 [5.2.1]: the logical offset is a constant expression.
4912 if (Offset.isInvalid())
4913 return true;
4914 Bound.E = Offset.get();
4915 }
4916 // 'omp_num_args' is a whole bound, not an operand of a larger expression, so
4917 // nothing else may follow it.
4918 if (!Tok.isOneOf(tok::colon, tok::comma, tok::r_paren,
4919 tok::annot_pragma_openmp_end)) {
4920 Diag(Tok, diag::err_omp_num_args_invalid_form) << 1;
4921 return true;
4922 }
4923 return false;
4924}
4925
4928 bool IsError = false;
4929 ColonProtectionRAIIObject ColonRAII(*this);
4930 while (true) {
4931 SourceLocation ItemLoc = Tok.getLocation();
4932 // An omitted lower bound stands for 1, and is written as a leading ':'.
4933 OMPAdjustArgsItem::Bound LowerBound;
4934 bool ItemError = false;
4935 if (Tok.isNot(tok::colon)) {
4936 ItemError = ParseOpenMPAdjustArgsBound(LowerBound);
4937 if (ItemError) {
4938 IsError = true;
4939 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4941 }
4942 }
4943
4944 if (Tok.is(tok::colon)) {
4945 ConsumeToken();
4946 // An omitted upper bound stands for 'omp_num_args'.
4947 OMPAdjustArgsItem::Bound UpperBound;
4948 if (!Tok.isOneOf(tok::comma, tok::r_paren,
4949 tok::annot_pragma_openmp_end)) {
4950 if (ParseOpenMPAdjustArgsBound(UpperBound)) {
4951 ItemError = true;
4952 IsError = true;
4953 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4955 }
4956 }
4957 if (!ItemError) {
4958 OMPAdjustArgsItem Item;
4960 Item.Lower = LowerBound;
4961 Item.Upper = UpperBound;
4962 Items.push_back(Item);
4963 }
4964 } else if (!ItemError &&
4966 // Without a colon the item is a parameter name or a position, and is
4967 // stored as a regular expression.
4968 if (LowerBound.Kind == OMPAdjustArgsItem::Bound::NumArgs) {
4969 Diag(ItemLoc, diag::err_omp_num_args_invalid_form) << 0;
4970 IsError = true;
4971 } else {
4972 OMPAdjustArgsItem Item;
4973 Item.E = LowerBound.E;
4974 Items.push_back(Item);
4975 }
4976 }
4977
4978 // Separator handling mirrors the shared var-list loop, so that a malformed
4979 // item such as '1:2:3' diagnoses instead of silently mis-parsing.
4980 if (Tok.isNot(tok::comma)) {
4981 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4982 Diag(Tok, diag::err_omp_expected_punc)
4983 << getOpenMPClauseName(OMPC_adjust_args) << /*IsDirective=*/0;
4984 IsError = true;
4985 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4987 }
4988 if (Tok.isNot(tok::comma))
4989 break;
4990 }
4991 ConsumeToken();
4992 }
4993 return IsError;
4994}
4995
4996/// Parse step size expression. Returns true if parsing is successfull,
4997/// otherwise returns false.
4999 OpenMPClauseKind CKind, SourceLocation ELoc) {
5001 Sema &Actions = P.getActions();
5002 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
5003 /*DiscardedValue*/ false);
5004 if (Tail.isUsable()) {
5005 Data.DepModOrTailExpr = Tail.get();
5006 Token CurTok = P.getCurToken();
5007 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
5008 P.Diag(CurTok, diag::err_expected_punc) << "step expression";
5009 }
5010 return true;
5011 }
5012 return false;
5013}
5014
5015/// Parse 'allocate' clause modifiers.
5016/// If allocator-modifier exists, return an expression for it. For both
5017/// allocator and align modifiers, set Data fields as appropriate.
5018static ExprResult
5021 const Token &Tok = P.getCurToken();
5022 Preprocessor &PP = P.getPreprocessor();
5023 ExprResult Tail;
5024 ExprResult Val;
5025 SourceLocation RLoc;
5026 bool AllocatorSeen = false;
5027 bool AlignSeen = false;
5028 SourceLocation CurrentModifierLoc = Tok.getLocation();
5029 auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
5031
5032 // Modifiers did not exist before 5.1
5033 if (P.getLangOpts().OpenMP < 51)
5034 return P.ParseAssignmentExpression();
5035
5036 // An allocator-simple-modifier is exclusive and must appear alone. See
5037 // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
5038 // description of "exclusive" property. If we don't recognized an explicit
5039 // simple-/complex- modifier, assume we're looking at expression
5040 // representing allocator and consider ourselves done.
5041 if (CurrentModifier == OMPC_ALLOCATE_unknown)
5042 return P.ParseAssignmentExpression();
5043
5044 do {
5045 P.ConsumeToken();
5046 if (Tok.is(tok::l_paren)) {
5047 switch (CurrentModifier) {
5048 case OMPC_ALLOCATE_allocator: {
5049 if (AllocatorSeen) {
5050 P.Diag(Tok, diag::err_omp_duplicate_modifier)
5051 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
5052 << getOpenMPClauseName(Kind);
5053 } else {
5054 Data.AllocClauseModifiers.push_back(CurrentModifier);
5055 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
5056 }
5057 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
5058 tok::annot_pragma_openmp_end);
5059 AllocateT.consumeOpen();
5060 Tail = P.ParseAssignmentExpression();
5061 AllocateT.consumeClose();
5062 AllocatorSeen = true;
5063 break;
5064 }
5065 case OMPC_ALLOCATE_align: {
5066 if (AlignSeen) {
5067 P.Diag(Tok, diag::err_omp_duplicate_modifier)
5068 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
5069 << getOpenMPClauseName(Kind);
5070 } else {
5071 Data.AllocClauseModifiers.push_back(CurrentModifier);
5072 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
5073 }
5074 Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
5075 if (Val.isUsable())
5076 Data.AllocateAlignment = Val.get();
5077 AlignSeen = true;
5078 break;
5079 }
5080 default:
5081 llvm_unreachable("Unexpected allocate modifier");
5082 }
5083 } else {
5084 P.Diag(Tok, diag::err_expected) << tok::l_paren;
5085 }
5086 if (Tok.isNot(tok::comma))
5087 break;
5088 P.ConsumeToken();
5089 CurrentModifierLoc = Tok.getLocation();
5090 CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
5092 // A modifier followed by a comma implies another modifier.
5093 if (CurrentModifier == OMPC_ALLOCATE_unknown) {
5094 P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
5095 break;
5096 }
5097 } while (!AllocatorSeen || !AlignSeen);
5098 return Tail;
5099}
5100
5104 SmallVectorImpl<OMPAdjustArgsItem> &AdjustArgsItems) {
5105 UnqualifiedId UnqualifiedReductionId;
5106 bool InvalidReductionId = false;
5107 bool IsInvalidMapperModifier = false;
5108
5109 // Parse '('.
5110 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5111 if (T.expectAndConsume(diag::err_expected_lparen_after,
5112 getOpenMPClauseName(Kind).data()))
5113 return true;
5114
5115 bool HasIterator = false;
5116 bool InvalidIterator = false;
5117 bool NeedRParenForLinear = false;
5118 // Set when the OpenMP 6.0 'adjust_args' parameter list has already been
5119 // parsed by ParseOpenMPAdjustArgsList, so the shared list loop must be
5120 // skipped.
5121 bool ParsedAdjustArgsList = false;
5122 bool InvalidAdjustArgsList = false;
5123 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
5124 tok::annot_pragma_openmp_end);
5125 // Handle reduction-identifier for reduction clause.
5126 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
5127 Kind == OMPC_in_reduction) {
5128 Data.ExtraModifier = OMPC_REDUCTION_unknown;
5129 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
5130 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
5131 NextToken().is(tok::comma)) {
5132 // Parse optional reduction modifier.
5133 Data.ExtraModifier =
5134 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5135 Data.ExtraModifierLoc = Tok.getLocation();
5136 ConsumeToken();
5137 assert(Tok.is(tok::comma) && "Expected comma.");
5138 (void)ConsumeToken();
5139 }
5140 // Handle original(private / shared) Modifier
5141 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
5142 Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
5143 NextToken().is(tok::l_paren)) {
5144 // Parse original(private) modifier.
5145 ConsumeToken();
5146 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
5147 ParenT.consumeOpen();
5148 if (Tok.is(tok::kw_private)) {
5149 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
5150 Data.OriginalSharingModifierLoc = Tok.getLocation();
5151 ConsumeToken();
5152 } else if (Tok.is(tok::identifier) &&
5153 (PP.getSpelling(Tok) == "shared" ||
5154 PP.getSpelling(Tok) == "default")) {
5155 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
5156 Data.OriginalSharingModifierLoc = Tok.getLocation();
5157 ConsumeToken();
5158 } else {
5159 Diag(Tok.getLocation(), diag::err_expected)
5160 << "'private or shared or default'";
5161 SkipUntil(tok::r_paren);
5162 return false;
5163 }
5164 ParenT.consumeClose();
5165 if (!Tok.is(tok::comma)) {
5166 Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
5167 return false;
5168 }
5169 (void)ConsumeToken();
5170 }
5171 ColonProtectionRAIIObject ColonRAII(*this);
5172 if (getLangOpts().CPlusPlus)
5173 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
5174 /*ObjectType=*/nullptr,
5175 /*ObjectHasErrors=*/false,
5176 /*EnteringContext=*/false);
5177 InvalidReductionId = ParseReductionId(
5178 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
5179 if (InvalidReductionId) {
5180 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5182 }
5183 if (Tok.is(tok::colon))
5184 Data.ColonLoc = ConsumeToken();
5185 else
5186 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
5187 if (!InvalidReductionId)
5188 Data.ReductionOrMapperId =
5189 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
5190 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
5191 if (getLangOpts().OpenMP >= 50) {
5192 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
5193 // Handle optional dependence modifier.
5194 // iterator(iterators-definition)
5195 // where iterators-definition is iterator-specifier [,
5196 // iterators-definition ]
5197 // where iterator-specifier is [ iterator-type ] identifier =
5198 // range-specification
5199 HasIterator = true;
5201 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
5202 Data.DepModOrTailExpr = IteratorRes.get();
5203 // Parse ','
5204 ExpectAndConsume(tok::comma);
5205 }
5206 }
5207 // Handle dependency type for depend clause.
5208 ColonProtectionRAIIObject ColonRAII(*this);
5209 Data.ExtraModifier = getOpenMPSimpleClauseType(
5210 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5211 getLangOpts());
5212 Data.ExtraModifierLoc = Tok.getLocation();
5213 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
5214 (Kind == OMPC_doacross &&
5215 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
5216 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5218 } else {
5219 ConsumeToken();
5220 // Special processing for depend(source) clause.
5221 if (DKind == OMPD_ordered_standalone && Kind == OMPC_depend &&
5222 Data.ExtraModifier == OMPC_DEPEND_source) {
5223 // Parse ')'.
5224 T.consumeClose();
5225 return false;
5226 }
5227 }
5228 if (Tok.is(tok::colon)) {
5229 Data.ColonLoc = ConsumeToken();
5230 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
5231 Diag(Tok, DKind == OMPD_ordered_standalone
5232 ? diag::warn_pragma_expected_colon_r_paren
5233 : diag::warn_pragma_expected_colon)
5234 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
5235 }
5236 if (Kind == OMPC_doacross) {
5237 if (Tok.is(tok::identifier) &&
5238 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
5239 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
5240 ? OMPC_DOACROSS_source_omp_cur_iteration
5241 : OMPC_DOACROSS_sink_omp_cur_iteration;
5242 ConsumeToken();
5243 }
5244 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
5245 if (Tok.isNot(tok::minus)) {
5246 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5247 << getOpenMPClauseName(Kind) << 0 << 0;
5248 SkipUntil(tok::r_paren);
5249 return false;
5250 } else {
5251 ConsumeToken();
5252 SourceLocation Loc = Tok.getLocation();
5253 uint64_t Value = 0;
5254 if (Tok.isNot(tok::numeric_constant) ||
5255 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
5256 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
5257 << getOpenMPClauseName(Kind) << 0 << 0;
5258 SkipUntil(tok::r_paren);
5259 return false;
5260 }
5261 }
5262 }
5263 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
5264 if (Tok.isNot(tok::r_paren)) {
5265 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5266 << getOpenMPClauseName(Kind) << 1 << 1;
5267 SkipUntil(tok::r_paren);
5268 return false;
5269 }
5270 }
5271 // Only the 'sink' case has the expression list.
5272 if (Kind == OMPC_doacross &&
5273 (Data.ExtraModifier == OMPC_DOACROSS_source ||
5274 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
5275 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
5276 // Parse ')'.
5277 T.consumeClose();
5278 return false;
5279 }
5280 }
5281 } else if (Kind == OMPC_linear) {
5282 // Try to parse modifier if any.
5283 Data.ExtraModifier = OMPC_LINEAR_val;
5284 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
5285 Data.ExtraModifier =
5286 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5287 Data.ExtraModifierLoc = ConsumeToken();
5288 LinearT.consumeOpen();
5289 NeedRParenForLinear = true;
5290 if (getLangOpts().OpenMP >= 52)
5291 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
5292 << "linear-modifier(list)" << getOpenMPClauseName(Kind)
5293 << "linear(list: [linear-modifier,] step(step-size))";
5294 }
5295 } else if (Kind == OMPC_lastprivate) {
5296 // Try to parse modifier if any.
5297 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
5298 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
5299 // distribute and taskloop based directives.
5300 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
5301 !isOpenMPTaskLoopDirective(DKind)) &&
5302 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
5303 Data.ExtraModifier =
5304 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5305 Data.ExtraModifierLoc = Tok.getLocation();
5306 ConsumeToken();
5307 assert(Tok.is(tok::colon) && "Expected colon.");
5308 Data.ColonLoc = ConsumeToken();
5309 }
5310 } else if (Kind == OMPC_map) {
5311 // Handle optional iterator map modifier.
5312 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
5313 HasIterator = true;
5315 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
5316 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
5317 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
5318 Data.IteratorExpr = IteratorRes.get();
5319 // Parse ','
5320 ExpectAndConsume(tok::comma);
5321 if (getLangOpts().OpenMP < 52) {
5322 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
5323 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
5324 << getLangOpts().OpenMPExtensions << 0;
5325 InvalidIterator = true;
5326 }
5327 }
5328 // Handle map type for map clause.
5329 ColonProtectionRAIIObject ColonRAII(*this);
5330
5331 // The first identifier may be a list item, a map-type or a
5332 // map-type-modifier. The map-type can also be delete which has the same
5333 // spelling of the C++ delete keyword.
5334 Data.ExtraModifier = OMPC_MAP_unknown;
5335 Data.ExtraModifierLoc = Tok.getLocation();
5336
5337 // Check for presence of a colon in the map clause.
5338 TentativeParsingAction TPA(*this);
5339 bool ColonPresent = false;
5340 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5341 StopBeforeMatch)) {
5342 if (Tok.is(tok::colon))
5343 ColonPresent = true;
5344 }
5345 TPA.Revert();
5346 // Only parse map-type-modifier[s] and map-type if a colon is present in
5347 // the map clause.
5348 if (ColonPresent) {
5349 if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
5350 Diag(Tok, diag::err_omp_map_modifier_specification_list);
5351 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
5352 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
5353 parseMapType(*this, Data);
5354 else
5355 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
5356 }
5357 if (Data.ExtraModifier == OMPC_MAP_unknown) {
5358 Data.ExtraModifier = OMPC_MAP_tofrom;
5359 if (getLangOpts().OpenMP >= 52) {
5360 if (DKind == OMPD_target_enter_data)
5361 Data.ExtraModifier = OMPC_MAP_to;
5362 else if (DKind == OMPD_target_exit_data)
5363 Data.ExtraModifier = OMPC_MAP_from;
5364 }
5365 Data.IsMapTypeImplicit = true;
5366 }
5367
5368 if (Tok.is(tok::colon))
5369 Data.ColonLoc = ConsumeToken();
5370 } else if (Kind == OMPC_to || Kind == OMPC_from) {
5371 while (Tok.is(tok::identifier)) {
5372 auto Modifier = static_cast<OpenMPMotionModifierKind>(
5373 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5374 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
5375 break;
5376 Data.MotionModifiers.push_back(Modifier);
5377 Data.MotionModifiersLoc.push_back(Tok.getLocation());
5378 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
5379 ExprResult Tail;
5380 Tail = ParseOpenMPIteratorsExpr();
5381 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5382 /*DiscardedValue=*/false);
5383 if (Tail.isUsable())
5384 Data.IteratorExpr = Tail.get();
5385 } else {
5386 ConsumeToken();
5387 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
5388 IsInvalidMapperModifier = parseMapperModifier(Data);
5389 if (IsInvalidMapperModifier)
5390 break;
5391 }
5392 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
5393 if (getLangOpts().OpenMP < 51)
5394 break;
5395 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
5396 // TODO: Is that intentional?
5397 if (Tok.is(tok::comma))
5398 ConsumeToken();
5399 }
5400 }
5401 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
5402 if (!IsInvalidMapperModifier) {
5403 if (getLangOpts().OpenMP < 51)
5404 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
5405 else
5406 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
5407 }
5408 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5410 }
5411 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
5412 // that intentional?
5413 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
5414 Tok.is(tok::colon))
5415 Data.ColonLoc = ConsumeToken();
5416 } else if (Kind == OMPC_allocate ||
5417 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
5418 PP.getSpelling(Tok) == "iterator")) {
5419 // Handle optional allocator and align modifiers followed by colon
5420 // delimiter.
5421 ColonProtectionRAIIObject ColonRAII(*this);
5422 TentativeParsingAction TPA(*this);
5423 // OpenMP 5.0, 2.10.1, task Construct.
5424 // where aff-modifier is one of the following:
5425 // iterator(iterators-definition)
5426 ExprResult Tail;
5427 if (Kind == OMPC_allocate) {
5428 Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
5429 } else {
5430 HasIterator = true;
5432 Tail = ParseOpenMPIteratorsExpr();
5433 }
5434 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5435 /*DiscardedValue=*/false);
5436 if (Tail.isUsable() || Data.AllocateAlignment) {
5437 if (Tok.is(tok::colon)) {
5438 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
5439 Data.ColonLoc = ConsumeToken();
5440 TPA.Commit();
5441 } else {
5442 // Colon not found, parse only list of variables.
5443 TPA.Revert();
5444 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
5445 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5447 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
5448 }
5449 }
5450 } else {
5451 // Parsing was unsuccessfull, revert and skip to the end of clause or
5452 // directive.
5453 TPA.Revert();
5454 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5456 }
5457 } else if (Kind == OMPC_adjust_args) {
5458 // Handle adjust-op for adjust_args clause.
5459 ColonProtectionRAIIObject ColonRAII(*this);
5460 Data.ExtraModifier = getOpenMPSimpleClauseType(
5461 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5462 getLangOpts());
5463 Data.ExtraModifierLoc = Tok.getLocation();
5464 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
5465 Diag(Tok, diag::err_omp_unknown_adjust_args_op)
5466 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
5467 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5468 } else {
5469 ConsumeToken();
5470 if (Tok.is(tok::colon))
5471 Data.ColonLoc = Tok.getLocation();
5472 if (getLangOpts().OpenMP >= 61) {
5473 // Handle the optional fallback argument for the need_device_ptr
5474 // modifier.
5475 if (Tok.is(tok::l_paren)) {
5476 BalancedDelimiterTracker T(*this, tok::l_paren);
5477 T.consumeOpen();
5478 if (Tok.is(tok::identifier)) {
5479 std::string Modifier = PP.getSpelling(Tok);
5480 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
5481 Data.NeedDevicePtrModifier =
5482 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
5483 : OMPC_NEED_DEVICE_PTR_fb_preserve;
5484 } else {
5485 Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);
5486 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5488 return false;
5489 }
5490 ConsumeToken();
5491 if (Tok.is(tok::r_paren)) {
5492 Data.NeedDevicePtrModifierLoc = Tok.getLocation();
5494 } else {
5495 Diag(Tok, diag::err_expected) << tok::r_paren;
5496 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5498 return false;
5499 }
5500 } else {
5501 Data.NeedDevicePtrModifier = OMPC_NEED_DEVICE_PTR_unknown;
5502 }
5503 }
5504 }
5505 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
5506 "adjust-op");
5507 // OpenMP 6.0 [5.2.1, Parameter List Items] adds positions and parameter
5508 // ranges, which the shared list loop below cannot express because a range
5509 // colon terminates it.
5510 if (getLangOpts().OpenMP >= 60) {
5511 ParsedAdjustArgsList = true;
5512 InvalidAdjustArgsList = ParseOpenMPAdjustArgsList(AdjustArgsItems);
5513 }
5514 }
5515 } else if (Kind == OMPC_use_device_ptr) {
5516 // Handle optional fallback modifier for use_device_ptr clause.
5517 // use_device_ptr([fb_preserve | fb_nullify :] list)
5519 if (getLangOpts().OpenMP >= 61 && Tok.is(tok::identifier)) {
5520 auto FallbackModifier = static_cast<OpenMPUseDevicePtrFallbackModifier>(
5521 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5522 if (FallbackModifier != OMPC_USE_DEVICE_PTR_FALLBACK_unknown) {
5523 Data.ExtraModifier = FallbackModifier;
5524 Data.ExtraModifierLoc = Tok.getLocation();
5525 ConsumeToken();
5526 if (Tok.is(tok::colon))
5527 Data.ColonLoc = ConsumeToken();
5528 else
5529 Diag(Tok, diag::err_modifier_expected_colon) << "fallback";
5530 }
5531 }
5532 } else if (Kind == OMPC_num_teams || Kind == OMPC_thread_limit) {
5533 int Mod = 0;
5534 // Handle optional dims and lower-bound modifiers for num_teams clause, and
5535 // the optional dims modifier for thread_limit clause.
5536 Data.ExtraModifierArray[0] = Data.ExtraModifierArray[1] =
5537 Kind == OMPC_num_teams ? static_cast<int>(OMPC_NUMTEAMS_unknown)
5538 : static_cast<int>(OMPC_THREADLIMIT_unknown);
5539
5540 // Lower-bound modifier is only accepted in num_teams.
5541 bool CanParseLowerBoundModifier = (Kind == OMPC_num_teams);
5542 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("dims") &&
5543 NextToken().is(tok::l_paren)) {
5544 SourceLocation TLoc = Tok.getLocation();
5545 ConsumeToken();
5546 SourceLocation RLoc;
5547 ExprResult ExprR = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
5548 if (ExprR.isUsable()) {
5549 Data.ExtraModifierArray[Mod] =
5550 Kind == OMPC_num_teams ? static_cast<int>(OMPC_NUMTEAMS_dims)
5551 : static_cast<int>(OMPC_THREADLIMIT_dims);
5552 Data.ExtraModifierExprArray[Mod] = ExprR.get();
5553 Data.ExtraModifierLocArray[Mod] = TLoc;
5554 ++Mod;
5555 }
5556
5557 if (Tok.is(tok::colon)) {
5558 // A colon was found, no more modifiers are expected.
5559 ConsumeToken();
5560 CanParseLowerBoundModifier = false;
5561 } else if (CanParseLowerBoundModifier && Tok.is(tok::comma)) {
5562 // num_teams(dims(N), lower : upper) is invalid. Only lower:upper may
5563 // follow dims via comma, but sema will reject the combination.
5564 ConsumeToken();
5565 } else {
5566 Diag(Tok, diag::err_modifier_expected_colon)
5567 << getOpenMPClauseName(Kind);
5568 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5569 Data.RLoc = Tok.getLocation();
5570 if (!T.consumeClose())
5571 Data.RLoc = T.getCloseLocation();
5572 return true;
5573 }
5574 }
5575
5576 // The lower bound modifier must appear as the last modifier.
5577 if (CanParseLowerBoundModifier) {
5578 TentativeParsingAction TPA(*this);
5579 SourceLocation TLoc = Tok.getLocation();
5581 if (FirstExpr.isInvalid()) {
5582 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5583 Data.RLoc = Tok.getLocation();
5584 if (!T.consumeClose())
5585 Data.RLoc = T.getCloseLocation();
5586 TPA.Commit();
5587 return true;
5588 }
5589
5590 if (Tok.is(tok::colon)) {
5591 // Correctly parsed the lower bound modifier.
5592 ConsumeToken();
5593 Data.ExtraModifierArray[Mod] = OMPC_NUMTEAMS_lower_bound;
5594 Data.ExtraModifierExprArray[Mod] = FirstExpr.get();
5595 Data.ExtraModifierLocArray[Mod] = TLoc;
5596 TPA.Commit();
5597 } else {
5598 // Could not find the colon after the expression, revert it and let this
5599 // function parse it as a list of expressions.
5600 TPA.Revert();
5601 }
5602 }
5603 } else if (Kind == OMPC_num_threads) {
5604 Data.ExtraModifierArray[0] = static_cast<int>(OMPC_NUMTHREADS_unknown);
5605 Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_unknown);
5606
5607 bool HasModifier = false;
5608 while (true) {
5609 if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("dims") &&
5610 NextToken().is(tok::l_paren)) {
5611 // Parse the dims modifier.
5612 SourceLocation TLoc = Tok.getLocation();
5613 ConsumeToken();
5614 SourceLocation RLoc;
5615
5616 ExprResult ExprR =
5617 ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
5618
5619 if (Data.ExtraModifierArray[1] != OMPC_NUMTHREADS_unknown)
5620 Diag(TLoc, diag::err_omp_incompatible_modifiers)
5621 << getOpenMPSimpleClauseTypeName(Kind, OMPC_NUMTHREADS_dims)
5622 << getOpenMPSimpleClauseTypeName(Kind, Data.ExtraModifierArray[1])
5623 << getOpenMPClauseName(Kind);
5624
5625 Data.ExtraModifierArray[1] = static_cast<int>(OMPC_NUMTHREADS_dims);
5626 Data.ExtraModifierExprArray[1] =
5627 (ExprR.isUsable()) ? ExprR.get() : nullptr;
5628 Data.ExtraModifierLocArray[1] = TLoc;
5629 HasModifier = true;
5630 } else {
5631 // Parse any other modifier.
5633 static_cast<OpenMPNumThreadsClauseModifier>(
5635 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5636 getLangOpts()));
5637
5638 if (Modifier != OMPC_NUMTHREADS_unknown) {
5639 if (Data.ExtraModifierArray[0] != OMPC_NUMTHREADS_unknown)
5640 Diag(Tok, diag::err_omp_incompatible_modifiers)
5641 << getOpenMPSimpleClauseTypeName(Kind, Modifier)
5643 Data.ExtraModifierArray[0])
5644 << getOpenMPClauseName(Kind);
5645 Data.ExtraModifierArray[0] = Modifier;
5646 Data.ExtraModifierLocArray[0] = Tok.getLocation();
5648 HasModifier = true;
5649 } else {
5650 // Not a recognized modifier.
5651 break;
5652 }
5653 }
5654
5655 // If a comma is present, continue parsing modifiers, and stop otherwise.
5656 if (Tok.is(tok::comma))
5657 ConsumeToken();
5658 else
5659 break;
5660 }
5661
5662 // If any modifier was parsed, the next token must be a colon.
5663 if (HasModifier) {
5664 if (!Tok.is(tok::colon)) {
5665 Diag(Tok, diag::err_modifier_expected_colon)
5666 << getOpenMPClauseName(Kind);
5667 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5668 Data.RLoc = Tok.getLocation();
5669 if (!T.consumeClose())
5670 Data.RLoc = T.getCloseLocation();
5671 return true;
5672 }
5673 ConsumeToken();
5674 }
5675 }
5676
5677 bool IsComma =
5678 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
5679 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
5680 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
5681 (Kind == OMPC_reduction && !InvalidReductionId) ||
5682 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
5683 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
5684 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
5685 (Kind == OMPC_adjust_args &&
5686 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
5687 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
5688 while (!ParsedAdjustArgsList &&
5689 (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
5690 Tok.isNot(tok::annot_pragma_openmp_end)))) {
5691 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
5692 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
5694 // Parse variable
5696 if (VarExpr.isUsable()) {
5697 Vars.push_back(VarExpr.get());
5698 } else {
5699 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5701 }
5702 }
5703 // Skip ',' if any
5704 IsComma = Tok.is(tok::comma);
5705 if (IsComma)
5706 ConsumeToken();
5707 else if (Tok.isNot(tok::r_paren) &&
5708 Tok.isNot(tok::annot_pragma_openmp_end) &&
5709 (!MayHaveTail || Tok.isNot(tok::colon))) {
5710 llvm::omp::Version OMPVersion = Actions.getLangOpts().getOpenMPVersion();
5711 Diag(Tok, diag::err_omp_expected_punc)
5712 << ((Kind == OMPC_flush)
5713 ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
5714 : getOpenMPClauseName(Kind))
5715 << (Kind == OMPC_flush);
5716 }
5717 }
5718
5719 // Parse ')' for linear clause with modifier.
5720 if (NeedRParenForLinear)
5721 LinearT.consumeClose();
5722 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
5723 // or parse ':' alignment.
5724 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
5725 bool StepFound = false;
5726 bool ModifierFound = false;
5727 if (MustHaveTail) {
5728 Data.ColonLoc = Tok.getLocation();
5730
5731 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
5732 bool Malformed = false;
5733 while (Tok.isNot(tok::r_paren)) {
5734 if (Tok.is(tok::identifier)) {
5735 // identifier could be a linear kind (val, uval, ref) or step
5736 // modifier or step size
5737 OpenMPLinearClauseKind LinKind =
5739 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5740 getLangOpts()));
5741
5742 if (LinKind == OMPC_LINEAR_step) {
5743 if (StepFound)
5744 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
5745
5746 BalancedDelimiterTracker StepT(*this, tok::l_paren,
5747 tok::annot_pragma_openmp_end);
5748 SourceLocation StepModifierLoc = ConsumeToken();
5749 // parse '('
5750 if (StepT.consumeOpen())
5751 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
5752
5753 // parse step size expression
5754 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5755 if (StepFound)
5756 Data.StepModifierLoc = StepModifierLoc;
5757
5758 // parse ')'
5759 StepT.consumeClose();
5760 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
5761 if (ModifierFound)
5762 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
5763
5764 Data.ExtraModifier = LinKind;
5765 Data.ExtraModifierLoc = ConsumeToken();
5766 ModifierFound = true;
5767 } else {
5768 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5769 if (!StepFound) {
5770 Malformed = true;
5771 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5773 }
5774 }
5775 } else {
5776 // parse an integer expression as step size
5777 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5778 }
5779
5780 if (Tok.is(tok::comma))
5781 ConsumeToken();
5782 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
5783 break;
5784 }
5785 if (!Malformed && !StepFound && !ModifierFound)
5786 Diag(ELoc, diag::err_expected_expression);
5787 } else {
5788 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
5790 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
5791 /*DiscardedValue*/ false);
5792 if (Tail.isUsable())
5793 Data.DepModOrTailExpr = Tail.get();
5794 else
5795 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5797 }
5798 }
5799
5800 // Parse ')'.
5801 Data.RLoc = Tok.getLocation();
5802 if (!T.consumeClose())
5803 Data.RLoc = T.getCloseLocation();
5804 // Exit from scope when the iterator is used in depend clause.
5805 if (HasIterator)
5806 ExitScope();
5807 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5808 Vars.empty() && AdjustArgsItems.empty()) ||
5809 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5810 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator ||
5811 InvalidAdjustArgsList;
5812}
5813
5814OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5815 OpenMPClauseKind Kind,
5816 bool ParseOnly) {
5817 SourceLocation Loc = Tok.getLocation();
5818 SourceLocation LOpen = ConsumeToken();
5820 SmallVector<OMPAdjustArgsItem> AdjustArgsItems;
5822
5823 if (ParseOpenMPVarList(DKind, Kind, Vars, Data, AdjustArgsItems))
5824 return nullptr;
5825
5826 if (ParseOnly)
5827 return nullptr;
5828 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5829 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5830}
5831
5832bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5833 SourceLocation &ClauseNameLoc,
5834 SourceLocation &OpenLoc,
5835 SourceLocation &CloseLoc,
5837 bool ReqIntConst) {
5838 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5839 "Expected parsing to start at clause name");
5840 ClauseNameLoc = ConsumeToken();
5841
5842 // Parse inside of '(' and ')'.
5843 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5844 if (T.consumeOpen()) {
5845 Diag(Tok, diag::err_expected) << tok::l_paren;
5846 return true;
5847 }
5848
5849 // Parse the list with interleaved commas.
5850 do {
5851 ExprResult Val =
5853 if (!Val.isUsable()) {
5854 // Encountered something other than an expression; abort to ')'.
5855 T.skipToEnd();
5856 return true;
5857 }
5858 Exprs.push_back(Val.get());
5859 } while (TryConsumeToken(tok::comma));
5860
5861 bool Result = T.consumeClose();
5862 OpenLoc = T.getOpenLocation();
5863 CloseLoc = T.getCloseLocation();
5864 return Result;
5865}
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.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
DeclarationNameTable DeclarationNames
Definition ASTContext.h:856
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:77
bool isEmpty() const
No scope specifier.
Definition DeclSpec.h:182
TypeSpecifierType TST
Definition DeclSpec.h:251
static const TST TST_unspecified
Definition DeclSpec.h:252
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:1137
SourceLocation getLocation() const
Definition DeclBase.h:448
DeclContext * getDeclContext()
Definition DeclBase.h:457
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:440
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:179
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:196
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition Expr.h:243
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:225
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
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:276
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition Decl.cpp:1977
This is a basic class for representing single OpenMP clause.
static const ParsedAttributesView & none()
Definition ParsedAttr.h:838
ParsedAttributes - A collection of parsed attributes.
Definition ParsedAttr.h:958
Introduces zero or more scopes for parsing.
Definition Parser.h:537
void Enter(unsigned ScopeFlags)
Definition Parser.h:545
ParseScope - Introduces a new scope for parsing.
Definition Parser.h:501
Parser - This implements a parser for the C family of languages.
Definition Parser.h:264
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:100
Preprocessor & getPreprocessor() const
Definition Parser.h:300
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:356
bool ParseOpenMPAdjustArgsList(SmallVectorImpl< OMPAdjustArgsItem > &Items)
Parses an OpenMP 6.0 'adjust_args' parameter list, whose items may be parameter names,...
Sema & getActions() const
Definition Parser.h:301
void EnterScope(unsigned ScopeFlags)
EnterScope - Start a new scope.
Definition Parser.cpp:438
bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
friend class ParsingOpenMPDirectiveRAII
Definition Parser.h:6433
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:289
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
Definition Parser.h:384
ExprResult ParseConstantExpression()
bool TryConsumeToken(tok::TokenKind Expected)
Definition Parser.h:364
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition Parser.h:313
Scope * getCurScope() const
Definition Parser.h:305
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data, SmallVectorImpl< OMPAdjustArgsItem > &AdjustArgsItems)
Parses clauses with list.
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:600
const Token & getCurToken() const
Definition Parser.h:304
bool ParseOpenMPAdjustArgsBound(OMPAdjustArgsItem::Bound &Bound)
Parses one bound of an OpenMP 6.0 'adjust_args' parameter range, which may be 'omp_num_args' with an ...
void ExitScope()
ExitScope - Pop a scope off the scope stack.
Definition Parser.cpp:448
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:298
friend class ParenBraceBracketBalancer
Definition Parser.h:292
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:581
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:418
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:293
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:4476
@ 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:8604
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:862
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1164
SemaOpenMP & OpenMP()
Definition Sema.h:1558
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:934
const LangOptions & getLangOpts() const
Definition Sema.h:927
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6856
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8817
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:1844
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:1043
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:725
Represents a variable declaration or definition.
Definition Decl.h:934
Defines the clang::TargetInfo interface.
PRESERVE_NONE bool Ret(InterpState &S)
Definition Interp.h:278
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:930
OpenMPNeedDevicePtrModifier
OpenMP 6.1 need_device modifier.
@ OMPC_NEED_DEVICE_PTR_unknown
OpenMPAdjustArgsOpKind
OpenMP adjust-op kinds for 'adjust_args' clause.
@ 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:1927
@ 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:1260
@ 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.
One bound of a parameter range.
Expr * E
The bound expression, or the logical offset for a NumArgs bound.
One item in an OpenMP 'adjust_args' parameter list.
Expr * E
A named parameter or positional expression for a Single item.
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:332
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition SemaOpenMP.h:329
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition SemaOpenMP.h:326
SourceLocation Loc
The directive location.
Definition SemaOpenMP.h:335
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition SemaOpenMP.h:323
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.