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, 3))
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 /*IgnoreArch=*/true))
3856 Attrs.push_back(A);
3857 continue;
3858 default:
3859 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3860 continue;
3861 };
3862 }
3863
3864 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
3865 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
3866}
3867
3868OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
3869 bool ParseOnly) {
3870 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
3871 if (!Val || ParseOnly)
3872 return nullptr;
3873 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3874 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
3875 static_cast<DefaultKind>(Val->Type) ==
3876 OMP_DEFAULT_firstprivate)) {
3877 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3878 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
3879 OMP_DEFAULT_private
3880 ? OMPC_private
3881 : OMPC_firstprivate)
3882 << getOpenMPClauseName(OMPC_default) << "5.1";
3883 return nullptr;
3884 }
3885 return Actions.OpenMP().ActOnOpenMPSimpleClause(
3886 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
3887}
3888
3889OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
3890 SourceLocation Loc = Tok.getLocation();
3892
3893 if (ParseOnly)
3894 return nullptr;
3895 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
3896}
3897
3898OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
3899 OpenMPClauseKind Kind,
3900 bool ParseOnly) {
3901 SourceLocation Loc = ConsumeToken();
3902 SourceLocation DelimLoc;
3903 // Parse '('.
3904 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3905 if (T.expectAndConsume(diag::err_expected_lparen_after,
3906 getOpenMPClauseName(Kind).data()))
3907 return nullptr;
3908
3909 ExprResult Val;
3910 SmallVector<unsigned, 4> Arg;
3911 SmallVector<SourceLocation, 4> KLoc;
3912 if (Kind == OMPC_schedule) {
3913 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3914 Arg.resize(NumberOfElements);
3915 KLoc.resize(NumberOfElements);
3916 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
3917 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
3918 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
3919 unsigned KindModifier = getOpenMPSimpleClauseType(
3920 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3921 if (KindModifier > OMPC_SCHEDULE_unknown) {
3922 // Parse 'modifier'
3923 Arg[Modifier1] = KindModifier;
3924 KLoc[Modifier1] = Tok.getLocation();
3925 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3926 Tok.isNot(tok::annot_pragma_openmp_end))
3928 if (Tok.is(tok::comma)) {
3929 // Parse ',' 'modifier'
3931 KindModifier = getOpenMPSimpleClauseType(
3932 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3933 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
3934 ? KindModifier
3935 : (unsigned)OMPC_SCHEDULE_unknown;
3936 KLoc[Modifier2] = Tok.getLocation();
3937 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3938 Tok.isNot(tok::annot_pragma_openmp_end))
3940 }
3941 // Parse ':'
3942 if (Tok.is(tok::colon))
3944 else
3945 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
3946 KindModifier = getOpenMPSimpleClauseType(
3947 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3948 }
3949 Arg[ScheduleKind] = KindModifier;
3950 KLoc[ScheduleKind] = Tok.getLocation();
3951 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3952 Tok.isNot(tok::annot_pragma_openmp_end))
3954 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3955 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3956 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3957 Tok.is(tok::comma))
3958 DelimLoc = ConsumeAnyToken();
3959 } else if (Kind == OMPC_dist_schedule) {
3960 Arg.push_back(getOpenMPSimpleClauseType(
3961 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3962 KLoc.push_back(Tok.getLocation());
3963 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3964 Tok.isNot(tok::annot_pragma_openmp_end))
3966 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
3967 DelimLoc = ConsumeAnyToken();
3968 } else if (Kind == OMPC_default) {
3969 // Get a default modifier
3970 unsigned Modifier = getOpenMPSimpleClauseType(
3971 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3972
3973 Arg.push_back(Modifier);
3974 KLoc.push_back(Tok.getLocation());
3975 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3976 Tok.isNot(tok::annot_pragma_openmp_end))
3978 // Parse ':'
3979 if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {
3981 // Get a variable-category attribute for default clause modifier
3982 OpenMPDefaultClauseVariableCategory VariableCategory =
3984 Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3985 Arg.push_back(VariableCategory);
3986 KLoc.push_back(Tok.getLocation());
3987 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3988 Tok.isNot(tok::annot_pragma_openmp_end))
3990 } else {
3991 Arg.push_back(OMPC_DEFAULT_VC_all);
3992 KLoc.push_back(SourceLocation());
3993 }
3994 } else if (Kind == OMPC_defaultmap) {
3995 // Get a defaultmap modifier
3996 unsigned Modifier = getOpenMPSimpleClauseType(
3997 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3998
3999 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
4000 // pointer
4001 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
4003 Arg.push_back(Modifier);
4004 KLoc.push_back(Tok.getLocation());
4005 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4006 Tok.isNot(tok::annot_pragma_openmp_end))
4008 // Parse ':'
4009 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
4010 if (Tok.is(tok::colon))
4012 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
4013 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
4014 // Get a defaultmap kind
4015 Arg.push_back(getOpenMPSimpleClauseType(
4016 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4017 KLoc.push_back(Tok.getLocation());
4018 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4019 Tok.isNot(tok::annot_pragma_openmp_end))
4021 } else {
4022 Arg.push_back(OMPC_DEFAULTMAP_unknown);
4023 KLoc.push_back(SourceLocation());
4024 }
4025 } else if (Kind == OMPC_order) {
4026 enum { Modifier, OrderKind, NumberOfElements };
4027 Arg.resize(NumberOfElements);
4028 KLoc.resize(NumberOfElements);
4029 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
4030 Arg[OrderKind] = OMPC_ORDER_unknown;
4031 unsigned KindModifier = getOpenMPSimpleClauseType(
4032 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4033 if (KindModifier > OMPC_ORDER_unknown) {
4034 // Parse 'modifier'
4035 Arg[Modifier] = KindModifier;
4036 KLoc[Modifier] = Tok.getLocation();
4037 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4038 Tok.isNot(tok::annot_pragma_openmp_end))
4040 // Parse ':'
4041 if (Tok.is(tok::colon))
4043 else
4044 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
4045 KindModifier = getOpenMPSimpleClauseType(
4046 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4047 }
4048 Arg[OrderKind] = KindModifier;
4049 KLoc[OrderKind] = Tok.getLocation();
4050 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4051 Tok.isNot(tok::annot_pragma_openmp_end))
4053 } else if (Kind == OMPC_device) {
4054 // Only target executable directives support extended device construct.
4055 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4056 NextToken().is(tok::colon)) {
4057 // Parse optional <device modifier> ':'
4058 Arg.push_back(getOpenMPSimpleClauseType(
4059 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4060 KLoc.push_back(Tok.getLocation());
4062 // Parse ':'
4064 } else {
4065 Arg.push_back(OMPC_DEVICE_unknown);
4066 KLoc.emplace_back();
4067 }
4068 } else if (Kind == OMPC_grainsize) {
4069 // Parse optional <grainsize modifier> ':'
4072 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4073 getLangOpts()));
4074 if (getLangOpts().OpenMP >= 51) {
4075 if (NextToken().is(tok::colon)) {
4076 Arg.push_back(Modifier);
4077 KLoc.push_back(Tok.getLocation());
4078 // Parse modifier
4080 // Parse ':'
4082 } else {
4083 if (Modifier == OMPC_GRAINSIZE_strict) {
4084 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4085 // Parse modifier
4087 }
4088 Arg.push_back(OMPC_GRAINSIZE_unknown);
4089 KLoc.emplace_back();
4090 }
4091 } else {
4092 Arg.push_back(OMPC_GRAINSIZE_unknown);
4093 KLoc.emplace_back();
4094 }
4095 } else if (Kind == OMPC_dyn_groupprivate) {
4096 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
4097 Arg.resize(NumberOfModifiers);
4098 KLoc.resize(NumberOfModifiers);
4099 Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
4100 Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
4101
4102 auto ConsumeModifier = [&]() {
4103 unsigned Type = NumberOfModifiers;
4104 unsigned Modifier;
4105 SourceLocation Loc;
4106 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
4107 NextToken().is(tok::l_paren)) {
4108 ConsumeToken();
4109 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4110 ParenT.consumeOpen();
4111
4112 Modifier = getOpenMPSimpleClauseType(
4113 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4116 Diag(Tok.getLocation(), diag::err_expected)
4117 << "'abort', 'null' or 'default_mem' in fallback modifier";
4118 SkipUntil(tok::r_paren);
4119 return std::make_tuple(Type, Modifier, Loc);
4120 }
4121 Type = ComplexModifier;
4122 Loc = Tok.getLocation();
4123 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4124 Tok.isNot(tok::annot_pragma_openmp_end))
4126 ParenT.consumeClose();
4127 } else {
4128 Modifier = getOpenMPSimpleClauseType(
4129 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4130 if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
4131 Type = SimpleModifier;
4132 Loc = Tok.getLocation();
4133 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4134 Tok.isNot(tok::annot_pragma_openmp_end))
4136 }
4137 }
4138 return std::make_tuple(Type, Modifier, Loc);
4139 };
4140
4141 auto SaveModifier = [&](unsigned Type, unsigned Modifier,
4142 SourceLocation Loc) {
4143 assert(Type < NumberOfModifiers && "Unexpected modifier type");
4144 if (!KLoc[Type].isValid()) {
4145 Arg[Type] = Modifier;
4146 KLoc[Type] = Loc;
4147 } else {
4148 Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
4149 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
4150 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
4151 }
4152 };
4153
4154 // Parse 'modifier'
4155 auto [Type1, Mod1, Loc1] = ConsumeModifier();
4156 if (Type1 < NumberOfModifiers) {
4157 SaveModifier(Type1, Mod1, Loc1);
4158 if (Tok.is(tok::comma)) {
4159 // Parse ',' 'modifier'
4161 auto [Type2, Mod2, Loc2] = ConsumeModifier();
4162 if (Type2 < NumberOfModifiers)
4163 SaveModifier(Type2, Mod2, Loc2);
4164 }
4165 // Parse ':'
4166 if (Tok.is(tok::colon))
4168 else
4169 Diag(Tok, diag::warn_pragma_expected_colon)
4170 << "dyn_groupprivate modifier";
4171 }
4172 } else if (Kind == OMPC_num_tasks) {
4173 // Parse optional <num_tasks modifier> ':'
4176 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4177 getLangOpts()));
4178 if (getLangOpts().OpenMP >= 51) {
4179 if (NextToken().is(tok::colon)) {
4180 Arg.push_back(Modifier);
4181 KLoc.push_back(Tok.getLocation());
4182 // Parse modifier
4184 // Parse ':'
4186 } else {
4187 if (Modifier == OMPC_NUMTASKS_strict) {
4188 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4189 // Parse modifier
4191 }
4192 Arg.push_back(OMPC_NUMTASKS_unknown);
4193 KLoc.emplace_back();
4194 }
4195 } else {
4196 Arg.push_back(OMPC_NUMTASKS_unknown);
4197 KLoc.emplace_back();
4198 }
4199 } else if (Kind == OMPC_num_threads) {
4200 // Parse optional <num_threads modifier> ':'
4203 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4204 getLangOpts()));
4205 if (getLangOpts().OpenMP >= 60) {
4206 if (NextToken().is(tok::colon)) {
4207 Arg.push_back(Modifier);
4208 KLoc.push_back(Tok.getLocation());
4209 // Parse modifier
4211 // Parse ':'
4213 } else {
4214 if (Modifier == OMPC_NUMTHREADS_strict) {
4215 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4216 // Parse modifier
4218 }
4219 Arg.push_back(OMPC_NUMTHREADS_unknown);
4220 KLoc.emplace_back();
4221 }
4222 } else {
4223 Arg.push_back(OMPC_NUMTHREADS_unknown);
4224 KLoc.emplace_back();
4225 }
4226 } else {
4227 assert(Kind == OMPC_if);
4228 KLoc.push_back(Tok.getLocation());
4229 TentativeParsingAction TPA(*this);
4230 auto DK = parseOpenMPDirectiveKind(*this);
4231 Arg.push_back(static_cast<unsigned>(DK));
4232 if (DK != OMPD_unknown) {
4233 ConsumeToken();
4234 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4235 TPA.Commit();
4236 DelimLoc = ConsumeToken();
4237 } else {
4238 TPA.Revert();
4239 Arg.back() = unsigned(OMPD_unknown);
4240 }
4241 } else {
4242 TPA.Revert();
4243 }
4244 }
4245
4246 bool NeedAnExpression =
4247 (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4248 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||
4249 Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
4250 Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;
4251 if (NeedAnExpression) {
4252 SourceLocation ELoc = Tok.getLocation();
4253 ExprResult LHS(
4254 ParseCastExpression(CastParseKind::AnyCastExpr, false,
4256 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4257 Val =
4258 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4259 }
4260
4261 // Parse ')'.
4262 SourceLocation RLoc = Tok.getLocation();
4263 if (!T.consumeClose())
4264 RLoc = T.getCloseLocation();
4265
4266 if (NeedAnExpression && Val.isInvalid())
4267 return nullptr;
4268
4269 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
4270 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
4271 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
4272 Diag(KLoc[0], diag::err_omp_invalid_dsa)
4273 << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==
4274 OMP_DEFAULT_private
4275 ? OMPC_private
4276 : OMPC_firstprivate)
4277 << getOpenMPClauseName(OMPC_default) << "5.1";
4278 return nullptr;
4279 }
4280
4281 if (ParseOnly)
4282 return nullptr;
4283 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4284 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4285}
4286
4287static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4288 UnqualifiedId &ReductionId) {
4289 if (ReductionIdScopeSpec.isEmpty()) {
4290 auto OOK = OO_None;
4291 switch (P.getCurToken().getKind()) {
4292 case tok::plus:
4293 OOK = OO_Plus;
4294 break;
4295 case tok::minus:
4296 OOK = OO_Minus;
4297 break;
4298 case tok::star:
4299 OOK = OO_Star;
4300 break;
4301 case tok::amp:
4302 OOK = OO_Amp;
4303 break;
4304 case tok::pipe:
4305 OOK = OO_Pipe;
4306 break;
4307 case tok::caret:
4308 OOK = OO_Caret;
4309 break;
4310 case tok::ampamp:
4311 OOK = OO_AmpAmp;
4312 break;
4313 case tok::pipepipe:
4314 OOK = OO_PipePipe;
4315 break;
4316 default:
4317 break;
4318 }
4319 if (OOK != OO_None) {
4320 SourceLocation OpLoc = P.ConsumeToken();
4321 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4322 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4323 return false;
4324 }
4325 }
4326 return P.ParseUnqualifiedId(
4327 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4328 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4329 /*AllowDestructorName*/ false,
4330 /*AllowConstructorName*/ false,
4331 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4332}
4333
4334/// Checks if the token is a valid map-type-modifier.
4335/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4337 Token Tok = P.getCurToken();
4338 if (!Tok.is(tok::identifier))
4340
4341 Preprocessor &PP = P.getPreprocessor();
4342 OpenMPMapModifierKind TypeModifier =
4344 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4345 return TypeModifier;
4346}
4347
4349 // Parse '('.
4350 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4351 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4352 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4354 return true;
4355 }
4356 // Parse mapper-identifier
4357 if (getLangOpts().CPlusPlus)
4358 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4359 /*ObjectType=*/nullptr,
4360 /*ObjectHasErrors=*/false,
4361 /*EnteringContext=*/false);
4362 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4363 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4364 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4366 return true;
4367 }
4368 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4369 Data.ReductionOrMapperId = DeclarationNameInfo(
4370 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4371 ConsumeToken();
4372 // Parse ')'.
4373 return T.consumeClose();
4374}
4375
4377
4379 bool HasMapType = false;
4380 SourceLocation PreMapLoc = Tok.getLocation();
4381 StringRef PreMapName = "";
4382 while (getCurToken().isNot(tok::colon)) {
4383 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4384 OpenMPMapClauseKind MapKind = isMapType(*this);
4385 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4386 TypeModifier == OMPC_MAP_MODIFIER_close ||
4387 TypeModifier == OMPC_MAP_MODIFIER_present ||
4388 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4389 Data.MapTypeModifiers.push_back(TypeModifier);
4390 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4391 if (PP.LookAhead(0).isNot(tok::comma) &&
4392 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4393 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4394 << "map type modifier";
4395 ConsumeToken();
4396 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4397 Data.MapTypeModifiers.push_back(TypeModifier);
4398 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4399 ConsumeToken();
4401 return true;
4402 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4403 getLangOpts().OpenMP >= 52)
4404 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4405 << "map type modifier";
4406
4407 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4408 if (!HasMapType) {
4409 HasMapType = true;
4410 Data.ExtraModifier = MapKind;
4411 MapKind = OMPC_MAP_unknown;
4412 PreMapLoc = Tok.getLocation();
4413 PreMapName = Tok.getIdentifierInfo()->getName();
4414 } else {
4415 Diag(Tok, diag::err_omp_more_one_map_type);
4416 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4417 << PreMapName;
4418 }
4419 ConsumeToken();
4420 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
4421 Data.MapTypeModifiers.push_back(TypeModifier);
4422 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4423 if (PP.LookAhead(0).isNot(tok::comma) &&
4424 PP.LookAhead(0).isNot(tok::colon))
4425 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4426 << "map type modifier";
4427 if (getLangOpts().OpenMP < 60)
4428 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4429 << (getLangOpts().OpenMP >= 51
4430 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4431 : 0)
4432 << getLangOpts().OpenMPExtensions << 0;
4433 ConsumeToken();
4434 } else {
4435 // For the case of unknown map-type-modifier or a map-type.
4436 // Map-type is followed by a colon; the function returns when it
4437 // encounters a token followed by a colon.
4438 if (Tok.is(tok::comma)) {
4439 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4440 ConsumeToken();
4441 continue;
4442 }
4443 // Potential map-type token as it is followed by a colon.
4444 if (PP.LookAhead(0).is(tok::colon)) {
4445 if (getLangOpts().OpenMP >= 60) {
4446 break;
4447 } else {
4448 return false;
4449 }
4450 }
4451
4452 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4453 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4454 : 0)
4455 << getLangOpts().OpenMPExtensions
4456 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
4457 ConsumeToken();
4458 }
4459 if (getCurToken().is(tok::comma))
4460 ConsumeToken();
4461 }
4462 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4463 if (!Tok.is(tok::colon)) {
4464 Diag(Tok, diag::err_omp_unknown_map_type);
4465 ConsumeToken();
4466 } else {
4467 Data.ExtraModifier = OMPC_MAP_unknown;
4468 }
4469 }
4470 return false;
4471}
4472
4473/// Checks if the token is a valid map-type.
4474/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4476 Token Tok = P.getCurToken();
4477 // The map-type token can be either an identifier or the C++ delete keyword.
4478 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4479 return OMPC_MAP_unknown;
4480 Preprocessor &PP = P.getPreprocessor();
4481 unsigned MapType =
4483 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4484 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4485 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4486 return static_cast<OpenMPMapClauseKind>(MapType);
4487 return OMPC_MAP_unknown;
4488}
4489
4490/// Parse map-type in map clause.
4491/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4492/// where, map-type ::= to | from | tofrom | alloc | release | delete
4494 Token Tok = P.getCurToken();
4495 if (Tok.is(tok::colon)) {
4496 P.Diag(Tok, diag::err_omp_map_type_missing);
4497 return;
4498 }
4499 Data.ExtraModifier = isMapType(P);
4500 if (Data.ExtraModifier == OMPC_MAP_unknown)
4501 P.Diag(Tok, diag::err_omp_unknown_map_type);
4502 P.ConsumeToken();
4503}
4504
4505ExprResult Parser::ParseOpenMPIteratorsExpr() {
4506 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4507 "Expected 'iterator' token.");
4508 SourceLocation IteratorKwLoc = ConsumeToken();
4509
4510 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4511 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4512 return ExprError();
4513
4514 SourceLocation LLoc = T.getOpenLocation();
4515 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4516 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4517 // Check if the type parsing is required.
4518 ParsedType IteratorType;
4519 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4520 // identifier '=' is not found - parse type.
4522 if (TR.isInvalid()) {
4523 T.skipToEnd();
4524 return ExprError();
4525 }
4526 IteratorType = TR.get();
4527 }
4528
4529 // Parse identifier.
4530 IdentifierInfo *II = nullptr;
4531 SourceLocation IdLoc;
4532 if (Tok.is(tok::identifier)) {
4533 II = Tok.getIdentifierInfo();
4534 IdLoc = ConsumeToken();
4535 } else {
4536 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4537 }
4538
4539 // Parse '='.
4540 SourceLocation AssignLoc;
4541 if (Tok.is(tok::equal))
4542 AssignLoc = ConsumeToken();
4543 else
4544 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4545
4546 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4547 ColonProtectionRAIIObject ColonRAII(*this);
4548 // Parse <begin>
4549 SourceLocation Loc = Tok.getLocation();
4550 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4551 ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4552 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4553 /*DiscardedValue=*/false);
4554 // Parse ':'.
4555 SourceLocation ColonLoc;
4556 if (Tok.is(tok::colon))
4557 ColonLoc = ConsumeToken();
4558
4559 // Parse <end>
4560 Loc = Tok.getLocation();
4561 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4562 ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4563 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4564 /*DiscardedValue=*/false);
4565
4566 SourceLocation SecColonLoc;
4567 ExprResult Step;
4568 // Parse optional step.
4569 if (Tok.is(tok::colon)) {
4570 // Parse ':'
4571 SecColonLoc = ConsumeToken();
4572 // Parse <step>
4573 Loc = Tok.getLocation();
4574 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4575 Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4576 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4577 /*DiscardedValue=*/false);
4578 }
4579
4580 // Parse ',' or ')'
4581 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4582 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4583 if (Tok.is(tok::comma))
4584 ConsumeToken();
4585
4586 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4587 D.DeclIdent = II;
4588 D.DeclIdentLoc = IdLoc;
4589 D.Type = IteratorType;
4590 D.AssignLoc = AssignLoc;
4591 D.ColonLoc = ColonLoc;
4592 D.SecColonLoc = SecColonLoc;
4593 D.Range.Begin = Begin.get();
4594 D.Range.End = End.get();
4595 D.Range.Step = Step.get();
4596 }
4597
4598 // Parse ')'.
4599 SourceLocation RLoc = Tok.getLocation();
4600 if (!T.consumeClose())
4601 RLoc = T.getCloseLocation();
4602
4603 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4604 LLoc, RLoc, Data);
4605}
4606
4609 const LangOptions &LangOpts) {
4610 // Currently the only reserved locator is 'omp_all_memory' which is only
4611 // allowed on a depend clause.
4612 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4613 return false;
4614
4615 if (Tok.is(tok::identifier) &&
4616 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4617
4618 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4619 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4620 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4621 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4622 Data.ExtraModifier != OMPC_DEPEND_inout)
4623 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4624 else
4625 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4626 ? OMPC_DEPEND_outallmemory
4627 : OMPC_DEPEND_inoutallmemory;
4628 ConsumeToken();
4629 return true;
4630 }
4631 return false;
4632}
4633
4634/// Parse step size expression. Returns true if parsing is successfull,
4635/// otherwise returns false.
4637 OpenMPClauseKind CKind, SourceLocation ELoc) {
4639 Sema &Actions = P.getActions();
4640 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4641 /*DiscardedValue*/ false);
4642 if (Tail.isUsable()) {
4643 Data.DepModOrTailExpr = Tail.get();
4644 Token CurTok = P.getCurToken();
4645 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4646 P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4647 }
4648 return true;
4649 }
4650 return false;
4651}
4652
4653/// Parse 'allocate' clause modifiers.
4654/// If allocator-modifier exists, return an expression for it. For both
4655/// allocator and align modifiers, set Data fields as appropriate.
4656static ExprResult
4659 const Token &Tok = P.getCurToken();
4660 Preprocessor &PP = P.getPreprocessor();
4661 ExprResult Tail;
4662 ExprResult Val;
4663 SourceLocation RLoc;
4664 bool AllocatorSeen = false;
4665 bool AlignSeen = false;
4666 SourceLocation CurrentModifierLoc = Tok.getLocation();
4667 auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4669
4670 // Modifiers did not exist before 5.1
4671 if (P.getLangOpts().OpenMP < 51)
4672 return P.ParseAssignmentExpression();
4673
4674 // An allocator-simple-modifier is exclusive and must appear alone. See
4675 // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
4676 // description of "exclusive" property. If we don't recognized an explicit
4677 // simple-/complex- modifier, assume we're looking at expression
4678 // representing allocator and consider ourselves done.
4679 if (CurrentModifier == OMPC_ALLOCATE_unknown)
4680 return P.ParseAssignmentExpression();
4681
4682 do {
4683 P.ConsumeToken();
4684 if (Tok.is(tok::l_paren)) {
4685 switch (CurrentModifier) {
4686 case OMPC_ALLOCATE_allocator: {
4687 if (AllocatorSeen) {
4688 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4689 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4690 << getOpenMPClauseName(Kind);
4691 } else {
4692 Data.AllocClauseModifiers.push_back(CurrentModifier);
4693 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4694 }
4695 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
4696 tok::annot_pragma_openmp_end);
4697 AllocateT.consumeOpen();
4698 Tail = P.ParseAssignmentExpression();
4699 AllocateT.consumeClose();
4700 AllocatorSeen = true;
4701 break;
4702 }
4703 case OMPC_ALLOCATE_align: {
4704 if (AlignSeen) {
4705 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4706 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4707 << getOpenMPClauseName(Kind);
4708 } else {
4709 Data.AllocClauseModifiers.push_back(CurrentModifier);
4710 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4711 }
4712 Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
4713 if (Val.isUsable())
4714 Data.AllocateAlignment = Val.get();
4715 AlignSeen = true;
4716 break;
4717 }
4718 default:
4719 llvm_unreachable("Unexpected allocate modifier");
4720 }
4721 } else {
4722 P.Diag(Tok, diag::err_expected) << tok::l_paren;
4723 }
4724 if (Tok.isNot(tok::comma))
4725 break;
4726 P.ConsumeToken();
4727 CurrentModifierLoc = Tok.getLocation();
4728 CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4730 // A modifier followed by a comma implies another modifier.
4731 if (CurrentModifier == OMPC_ALLOCATE_unknown) {
4732 P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
4733 break;
4734 }
4735 } while (!AllocatorSeen || !AlignSeen);
4736 return Tail;
4737}
4738
4740 OpenMPClauseKind Kind,
4743 UnqualifiedId UnqualifiedReductionId;
4744 bool InvalidReductionId = false;
4745 bool IsInvalidMapperModifier = false;
4746
4747 // Parse '('.
4748 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4749 if (T.expectAndConsume(diag::err_expected_lparen_after,
4750 getOpenMPClauseName(Kind).data()))
4751 return true;
4752
4753 bool HasIterator = false;
4754 bool InvalidIterator = false;
4755 bool NeedRParenForLinear = false;
4756 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4757 tok::annot_pragma_openmp_end);
4758 // Handle reduction-identifier for reduction clause.
4759 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4760 Kind == OMPC_in_reduction) {
4761 Data.ExtraModifier = OMPC_REDUCTION_unknown;
4762 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4763 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4764 NextToken().is(tok::comma)) {
4765 // Parse optional reduction modifier.
4766 Data.ExtraModifier =
4767 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4768 Data.ExtraModifierLoc = Tok.getLocation();
4769 ConsumeToken();
4770 assert(Tok.is(tok::comma) && "Expected comma.");
4771 (void)ConsumeToken();
4772 }
4773 // Handle original(private / shared) Modifier
4774 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
4775 Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
4776 NextToken().is(tok::l_paren)) {
4777 // Parse original(private) modifier.
4778 ConsumeToken();
4779 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4780 ParenT.consumeOpen();
4781 if (Tok.is(tok::kw_private)) {
4782 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
4783 Data.OriginalSharingModifierLoc = Tok.getLocation();
4784 ConsumeToken();
4785 } else if (Tok.is(tok::identifier) &&
4786 (PP.getSpelling(Tok) == "shared" ||
4787 PP.getSpelling(Tok) == "default")) {
4788 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
4789 Data.OriginalSharingModifierLoc = Tok.getLocation();
4790 ConsumeToken();
4791 } else {
4792 Diag(Tok.getLocation(), diag::err_expected)
4793 << "'private or shared or default'";
4794 SkipUntil(tok::r_paren);
4795 return false;
4796 }
4797 ParenT.consumeClose();
4798 if (!Tok.is(tok::comma)) {
4799 Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
4800 return false;
4801 }
4802 (void)ConsumeToken();
4803 }
4804 ColonProtectionRAIIObject ColonRAII(*this);
4805 if (getLangOpts().CPlusPlus)
4806 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4807 /*ObjectType=*/nullptr,
4808 /*ObjectHasErrors=*/false,
4809 /*EnteringContext=*/false);
4810 InvalidReductionId = ParseReductionId(
4811 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4812 if (InvalidReductionId) {
4813 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4815 }
4816 if (Tok.is(tok::colon))
4817 Data.ColonLoc = ConsumeToken();
4818 else
4819 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4820 if (!InvalidReductionId)
4821 Data.ReductionOrMapperId =
4822 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4823 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4824 if (getLangOpts().OpenMP >= 50) {
4825 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4826 // Handle optional dependence modifier.
4827 // iterator(iterators-definition)
4828 // where iterators-definition is iterator-specifier [,
4829 // iterators-definition ]
4830 // where iterator-specifier is [ iterator-type ] identifier =
4831 // range-specification
4832 HasIterator = true;
4834 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4835 Data.DepModOrTailExpr = IteratorRes.get();
4836 // Parse ','
4837 ExpectAndConsume(tok::comma);
4838 }
4839 }
4840 // Handle dependency type for depend clause.
4841 ColonProtectionRAIIObject ColonRAII(*this);
4842 Data.ExtraModifier = getOpenMPSimpleClauseType(
4843 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4844 getLangOpts());
4845 Data.ExtraModifierLoc = Tok.getLocation();
4846 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
4847 (Kind == OMPC_doacross &&
4848 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
4849 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4851 } else {
4852 ConsumeToken();
4853 // Special processing for depend(source) clause.
4854 if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4855 Data.ExtraModifier == OMPC_DEPEND_source) {
4856 // Parse ')'.
4857 T.consumeClose();
4858 return false;
4859 }
4860 }
4861 if (Tok.is(tok::colon)) {
4862 Data.ColonLoc = ConsumeToken();
4863 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
4864 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4865 : diag::warn_pragma_expected_colon)
4866 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
4867 }
4868 if (Kind == OMPC_doacross) {
4869 if (Tok.is(tok::identifier) &&
4870 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
4871 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
4872 ? OMPC_DOACROSS_source_omp_cur_iteration
4873 : OMPC_DOACROSS_sink_omp_cur_iteration;
4874 ConsumeToken();
4875 }
4876 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4877 if (Tok.isNot(tok::minus)) {
4878 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4879 << getOpenMPClauseName(Kind) << 0 << 0;
4880 SkipUntil(tok::r_paren);
4881 return false;
4882 } else {
4883 ConsumeToken();
4884 SourceLocation Loc = Tok.getLocation();
4885 uint64_t Value = 0;
4886 if (Tok.isNot(tok::numeric_constant) ||
4887 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
4888 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
4889 << getOpenMPClauseName(Kind) << 0 << 0;
4890 SkipUntil(tok::r_paren);
4891 return false;
4892 }
4893 }
4894 }
4895 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4896 if (Tok.isNot(tok::r_paren)) {
4897 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4898 << getOpenMPClauseName(Kind) << 1 << 1;
4899 SkipUntil(tok::r_paren);
4900 return false;
4901 }
4902 }
4903 // Only the 'sink' case has the expression list.
4904 if (Kind == OMPC_doacross &&
4905 (Data.ExtraModifier == OMPC_DOACROSS_source ||
4906 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4907 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4908 // Parse ')'.
4909 T.consumeClose();
4910 return false;
4911 }
4912 }
4913 } else if (Kind == OMPC_linear) {
4914 // Try to parse modifier if any.
4915 Data.ExtraModifier = OMPC_LINEAR_val;
4916 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
4917 Data.ExtraModifier =
4918 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4919 Data.ExtraModifierLoc = ConsumeToken();
4920 LinearT.consumeOpen();
4921 NeedRParenForLinear = true;
4922 if (getLangOpts().OpenMP >= 52)
4923 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
4924 << "linear-modifier(list)" << getOpenMPClauseName(Kind)
4925 << "linear(list: [linear-modifier,] step(step-size))";
4926 }
4927 } else if (Kind == OMPC_lastprivate) {
4928 // Try to parse modifier if any.
4929 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
4930 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4931 // distribute and taskloop based directives.
4932 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
4933 !isOpenMPTaskLoopDirective(DKind)) &&
4934 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
4935 Data.ExtraModifier =
4936 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4937 Data.ExtraModifierLoc = Tok.getLocation();
4938 ConsumeToken();
4939 assert(Tok.is(tok::colon) && "Expected colon.");
4940 Data.ColonLoc = ConsumeToken();
4941 }
4942 } else if (Kind == OMPC_map) {
4943 // Handle optional iterator map modifier.
4944 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4945 HasIterator = true;
4947 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4948 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4949 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4950 Data.IteratorExpr = IteratorRes.get();
4951 // Parse ','
4952 ExpectAndConsume(tok::comma);
4953 if (getLangOpts().OpenMP < 52) {
4954 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4955 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
4956 << getLangOpts().OpenMPExtensions << 0;
4957 InvalidIterator = true;
4958 }
4959 }
4960 // Handle map type for map clause.
4961 ColonProtectionRAIIObject ColonRAII(*this);
4962
4963 // The first identifier may be a list item, a map-type or a
4964 // map-type-modifier. The map-type can also be delete which has the same
4965 // spelling of the C++ delete keyword.
4966 Data.ExtraModifier = OMPC_MAP_unknown;
4967 Data.ExtraModifierLoc = Tok.getLocation();
4968
4969 // Check for presence of a colon in the map clause.
4970 TentativeParsingAction TPA(*this);
4971 bool ColonPresent = false;
4972 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4973 StopBeforeMatch)) {
4974 if (Tok.is(tok::colon))
4975 ColonPresent = true;
4976 }
4977 TPA.Revert();
4978 // Only parse map-type-modifier[s] and map-type if a colon is present in
4979 // the map clause.
4980 if (ColonPresent) {
4981 if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
4982 Diag(Tok, diag::err_omp_map_modifier_specification_list);
4983 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
4984 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
4985 parseMapType(*this, Data);
4986 else
4987 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
4988 }
4989 if (Data.ExtraModifier == OMPC_MAP_unknown) {
4990 Data.ExtraModifier = OMPC_MAP_tofrom;
4991 if (getLangOpts().OpenMP >= 52) {
4992 if (DKind == OMPD_target_enter_data)
4993 Data.ExtraModifier = OMPC_MAP_to;
4994 else if (DKind == OMPD_target_exit_data)
4995 Data.ExtraModifier = OMPC_MAP_from;
4996 }
4997 Data.IsMapTypeImplicit = true;
4998 }
4999
5000 if (Tok.is(tok::colon))
5001 Data.ColonLoc = ConsumeToken();
5002 } else if (Kind == OMPC_to || Kind == OMPC_from) {
5003 while (Tok.is(tok::identifier)) {
5004 auto Modifier = static_cast<OpenMPMotionModifierKind>(
5005 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5006 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
5007 break;
5008 Data.MotionModifiers.push_back(Modifier);
5009 Data.MotionModifiersLoc.push_back(Tok.getLocation());
5010 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
5011 ExprResult Tail;
5012 Tail = ParseOpenMPIteratorsExpr();
5013 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5014 /*DiscardedValue=*/false);
5015 if (Tail.isUsable())
5016 Data.IteratorExpr = Tail.get();
5017 } else {
5018 ConsumeToken();
5019 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
5020 IsInvalidMapperModifier = parseMapperModifier(Data);
5021 if (IsInvalidMapperModifier)
5022 break;
5023 }
5024 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
5025 if (getLangOpts().OpenMP < 51)
5026 break;
5027 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
5028 // TODO: Is that intentional?
5029 if (Tok.is(tok::comma))
5030 ConsumeToken();
5031 }
5032 }
5033 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
5034 if (!IsInvalidMapperModifier) {
5035 if (getLangOpts().OpenMP < 51)
5036 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
5037 else
5038 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
5039 }
5040 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5042 }
5043 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
5044 // that intentional?
5045 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
5046 Tok.is(tok::colon))
5047 Data.ColonLoc = ConsumeToken();
5048 } else if (Kind == OMPC_allocate ||
5049 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
5050 PP.getSpelling(Tok) == "iterator")) {
5051 // Handle optional allocator and align modifiers followed by colon
5052 // delimiter.
5053 ColonProtectionRAIIObject ColonRAII(*this);
5054 TentativeParsingAction TPA(*this);
5055 // OpenMP 5.0, 2.10.1, task Construct.
5056 // where aff-modifier is one of the following:
5057 // iterator(iterators-definition)
5058 ExprResult Tail;
5059 if (Kind == OMPC_allocate) {
5060 Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
5061 } else {
5062 HasIterator = true;
5064 Tail = ParseOpenMPIteratorsExpr();
5065 }
5066 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5067 /*DiscardedValue=*/false);
5068 if (Tail.isUsable() || Data.AllocateAlignment) {
5069 if (Tok.is(tok::colon)) {
5070 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
5071 Data.ColonLoc = ConsumeToken();
5072 TPA.Commit();
5073 } else {
5074 // Colon not found, parse only list of variables.
5075 TPA.Revert();
5076 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
5077 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5079 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
5080 }
5081 }
5082 } else {
5083 // Parsing was unsuccessfull, revert and skip to the end of clause or
5084 // directive.
5085 TPA.Revert();
5086 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5088 }
5089 } else if (Kind == OMPC_adjust_args) {
5090 // Handle adjust-op for adjust_args clause.
5091 ColonProtectionRAIIObject ColonRAII(*this);
5092 Data.ExtraModifier = getOpenMPSimpleClauseType(
5093 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5094 getLangOpts());
5095 Data.ExtraModifierLoc = Tok.getLocation();
5096 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
5097 Diag(Tok, diag::err_omp_unknown_adjust_args_op)
5098 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
5099 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5100 } else {
5101 ConsumeToken();
5102 if (Tok.is(tok::colon))
5103 Data.ColonLoc = Tok.getLocation();
5104 if (getLangOpts().OpenMP >= 61) {
5105 // Handle the optional fallback argument for the need_device_ptr
5106 // modifier.
5107 if (Tok.is(tok::l_paren)) {
5108 BalancedDelimiterTracker T(*this, tok::l_paren);
5109 T.consumeOpen();
5110 if (Tok.is(tok::identifier)) {
5111 std::string Modifier = PP.getSpelling(Tok);
5112 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
5113 Data.NeedDevicePtrModifier =
5114 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
5115 : OMPC_NEED_DEVICE_PTR_fb_preserve;
5116 } else {
5117 Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);
5118 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5120 return false;
5121 }
5122 ConsumeToken();
5123 if (Tok.is(tok::r_paren)) {
5124 Data.NeedDevicePtrModifierLoc = Tok.getLocation();
5126 } else {
5127 Diag(Tok, diag::err_expected) << tok::r_paren;
5128 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5130 return false;
5131 }
5132 } else {
5133 Data.NeedDevicePtrModifier = OMPC_NEED_DEVICE_PTR_unknown;
5134 }
5135 }
5136 }
5137 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
5138 "adjust-op");
5139 }
5140 } else if (Kind == OMPC_use_device_ptr) {
5141 // Handle optional fallback modifier for use_device_ptr clause.
5142 // use_device_ptr([fb_preserve | fb_nullify :] list)
5144 if (getLangOpts().OpenMP >= 61 && Tok.is(tok::identifier)) {
5145 auto FallbackModifier = static_cast<OpenMPUseDevicePtrFallbackModifier>(
5146 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5147 if (FallbackModifier != OMPC_USE_DEVICE_PTR_FALLBACK_unknown) {
5148 Data.ExtraModifier = FallbackModifier;
5149 Data.ExtraModifierLoc = Tok.getLocation();
5150 ConsumeToken();
5151 if (Tok.is(tok::colon))
5152 Data.ColonLoc = ConsumeToken();
5153 else
5154 Diag(Tok, diag::err_modifier_expected_colon) << "fallback";
5155 }
5156 }
5157 } // Handle num_teams clause with optional lower-bound:upper-bound syntax
5158 if (Kind == OMPC_num_teams && !Tok.is(tok::r_paren) &&
5159 !Tok.is(tok::annot_pragma_openmp_end)) {
5161 if (FirstExpr.isInvalid()) {
5162 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5163 Data.RLoc = Tok.getLocation();
5164 if (!T.consumeClose())
5165 Data.RLoc = T.getCloseLocation();
5166 return true;
5167 }
5168
5169 if (Tok.is(tok::colon)) {
5170 // Lower-bound:upper-bound syntax
5171 ConsumeToken();
5173 if (UpperBound.isInvalid()) {
5174 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5175 Data.RLoc = Tok.getLocation();
5176 if (!T.consumeClose())
5177 Data.RLoc = T.getCloseLocation();
5178 return true;
5179 }
5180 Vars.push_back(FirstExpr.get()); // lower-bound
5181 Vars.push_back(UpperBound.get()); // upper-bound
5182 Data.RLoc = Tok.getLocation();
5183 if (!T.consumeClose())
5184 Data.RLoc = T.getCloseLocation();
5185 return false; // Success
5186 }
5187 if (Tok.is(tok::comma)) {
5188 Vars.push_back(FirstExpr.get());
5189 while (Tok.is(tok::comma)) {
5190 ConsumeToken();
5192 if (NextExpr.isUsable()) {
5193 Vars.push_back(NextExpr.get());
5194 } else {
5195 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5197 break;
5198 }
5199 }
5200 Data.RLoc = Tok.getLocation();
5201 bool HadError = T.consumeClose();
5202 if (!HadError)
5203 Data.RLoc = T.getCloseLocation();
5204 return HadError;
5205 }
5206
5207 // Single value - parse closing paren
5208 Vars.push_back(FirstExpr.get());
5209 Data.RLoc = Tok.getLocation();
5210 if (!T.consumeClose())
5211 Data.RLoc = T.getCloseLocation();
5212 return false; // Success
5213 }
5214
5215 bool IsComma =
5216 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
5217 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
5218 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
5219 (Kind == OMPC_reduction && !InvalidReductionId) ||
5220 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
5221 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
5222 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
5223 (Kind == OMPC_adjust_args &&
5224 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
5225 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
5226 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
5227 Tok.isNot(tok::annot_pragma_openmp_end))) {
5228 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
5229 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
5231 // Parse variable
5233 if (VarExpr.isUsable()) {
5234 Vars.push_back(VarExpr.get());
5235 } else {
5236 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5238 }
5239 }
5240 // Skip ',' if any
5241 IsComma = Tok.is(tok::comma);
5242 if (IsComma)
5243 ConsumeToken();
5244 else if (Tok.isNot(tok::r_paren) &&
5245 Tok.isNot(tok::annot_pragma_openmp_end) &&
5246 (!MayHaveTail || Tok.isNot(tok::colon))) {
5247 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
5248 Diag(Tok, diag::err_omp_expected_punc)
5249 << ((Kind == OMPC_flush)
5250 ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
5251 : getOpenMPClauseName(Kind))
5252 << (Kind == OMPC_flush);
5253 }
5254 }
5255
5256 // Parse ')' for linear clause with modifier.
5257 if (NeedRParenForLinear)
5258 LinearT.consumeClose();
5259 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
5260 // or parse ':' alignment.
5261 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
5262 bool StepFound = false;
5263 bool ModifierFound = false;
5264 if (MustHaveTail) {
5265 Data.ColonLoc = Tok.getLocation();
5267
5268 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
5269 bool Malformed = false;
5270 while (Tok.isNot(tok::r_paren)) {
5271 if (Tok.is(tok::identifier)) {
5272 // identifier could be a linear kind (val, uval, ref) or step
5273 // modifier or step size
5274 OpenMPLinearClauseKind LinKind =
5276 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5277 getLangOpts()));
5278
5279 if (LinKind == OMPC_LINEAR_step) {
5280 if (StepFound)
5281 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
5282
5283 BalancedDelimiterTracker StepT(*this, tok::l_paren,
5284 tok::annot_pragma_openmp_end);
5285 SourceLocation StepModifierLoc = ConsumeToken();
5286 // parse '('
5287 if (StepT.consumeOpen())
5288 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
5289
5290 // parse step size expression
5291 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5292 if (StepFound)
5293 Data.StepModifierLoc = StepModifierLoc;
5294
5295 // parse ')'
5296 StepT.consumeClose();
5297 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
5298 if (ModifierFound)
5299 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
5300
5301 Data.ExtraModifier = LinKind;
5302 Data.ExtraModifierLoc = ConsumeToken();
5303 ModifierFound = true;
5304 } else {
5305 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5306 if (!StepFound) {
5307 Malformed = true;
5308 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5310 }
5311 }
5312 } else {
5313 // parse an integer expression as step size
5314 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5315 }
5316
5317 if (Tok.is(tok::comma))
5318 ConsumeToken();
5319 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
5320 break;
5321 }
5322 if (!Malformed && !StepFound && !ModifierFound)
5323 Diag(ELoc, diag::err_expected_expression);
5324 } else {
5325 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
5327 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
5328 /*DiscardedValue*/ false);
5329 if (Tail.isUsable())
5330 Data.DepModOrTailExpr = Tail.get();
5331 else
5332 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5334 }
5335 }
5336
5337 // Parse ')'.
5338 Data.RLoc = Tok.getLocation();
5339 if (!T.consumeClose())
5340 Data.RLoc = T.getCloseLocation();
5341 // Exit from scope when the iterator is used in depend clause.
5342 if (HasIterator)
5343 ExitScope();
5344 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5345 Vars.empty()) ||
5346 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5347 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5348}
5349
5350OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5351 OpenMPClauseKind Kind,
5352 bool ParseOnly) {
5353 SourceLocation Loc = Tok.getLocation();
5354 SourceLocation LOpen = ConsumeToken();
5357
5358 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5359 return nullptr;
5360
5361 if (ParseOnly)
5362 return nullptr;
5363 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5364 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5365}
5366
5367bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5368 SourceLocation &ClauseNameLoc,
5369 SourceLocation &OpenLoc,
5370 SourceLocation &CloseLoc,
5372 bool ReqIntConst) {
5373 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5374 "Expected parsing to start at clause name");
5375 ClauseNameLoc = ConsumeToken();
5376
5377 // Parse inside of '(' and ')'.
5378 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5379 if (T.consumeOpen()) {
5380 Diag(Tok, diag::err_expected) << tok::l_paren;
5381 return true;
5382 }
5383
5384 // Parse the list with interleaved commas.
5385 do {
5386 ExprResult Val =
5388 if (!Val.isUsable()) {
5389 // Encountered something other than an expression; abort to ')'.
5390 T.skipToEnd();
5391 return true;
5392 }
5393 Exprs.push_back(Val.get());
5394 } while (TryConsumeToken(tok::comma));
5395
5396 bool Result = T.consumeClose();
5397 OpenLoc = T.getOpenLocation();
5398 CloseLoc = T.getCloseLocation();
5399 return Result;
5400}
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:76
bool isEmpty() const
No scope specifier.
Definition DeclSpec.h:181
TypeSpecifierType TST
Definition DeclSpec.h:250
static const TST TST_unspecified
Definition DeclSpec.h:251
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition DeclBase.h: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:528
void Enter(unsigned ScopeFlags)
Definition Parser.h:536
ParseScope - Introduces a new scope for parsing.
Definition Parser.h:492
Parser - This implements a parser for the C family of languages.
Definition Parser.h:256
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data)
Parses clauses with list.
TypeResult ParseTypeName(SourceRange *Range=nullptr, DeclaratorContext Context=DeclaratorContext::TypeName, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)
ParseTypeName.
Definition ParseDecl.cpp:44
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Definition Parser.cpp:88
Preprocessor & getPreprocessor() const
Definition Parser.h:291
bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type-modifiers in map clause.
ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral=false)
ParseStringLiteralExpression - This handles the various token types that form string literals,...
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Definition Parser.h:347
Sema & getActions() const
Definition Parser.h:292
void EnterScope(unsigned ScopeFlags)
EnterScope - Start a new scope.
Definition Parser.cpp:428
bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
friend class ParsingOpenMPDirectiveRAII
Definition Parser.h:6393
bool ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
friend class ColonProtectionRAIIObject
Definition Parser.h:281
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
Definition Parser.h:375
ExprResult ParseConstantExpression()
bool TryConsumeToken(tok::TokenKind Expected)
Definition Parser.h:355
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition Parser.h:304
Scope * getCurScope() const
Definition Parser.h:296
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
Definition Parser.h:591
const Token & getCurToken() const
Definition Parser.h:295
void ExitScope()
ExitScope - Pop a scope off the scope stack.
Definition Parser.cpp: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:289
friend class ParenBraceBracketBalancer
Definition Parser.h:283
ExprResult ParseExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Simple precedence-based parser for binary/ternary operators.
Definition ParseExpr.cpp:47
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
Definition Parser.h:572
bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)
Parses a reserved locator like 'omp_all_memory'.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
Definition Parser.h:409
ExprResult ParseAssignmentExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Parse an expr that doesn't include (top-level) commas.
Definition ParseExpr.cpp:75
friend class BalancedDelimiterTracker
Definition Parser.h:284
unsigned ReenterTemplateScopes(MultiParseScope &S, Decl *D)
Re-enter a possible template scope, creating as many template parameter scopes as necessary.
bool ParseOpenMPDeclareBeginVariantDirective(SourceLocation Loc)
Parses 'omp begin declare variant' directive.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
Represents a struct/union/class.
Definition Decl.h:4343
@ 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:8534
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:6792
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8745
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:1875
QualType getCanonicalTypeInternal() const
Definition TypeBase.h:3181
Represents a C++ unqualified-id that has been parsed.
Definition DeclSpec.h:1035
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:924
Defines the clang::TargetInfo interface.
PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC)
Definition Interp.h:258
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:1898
@ 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:1252
@ 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.