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