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