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
1288 // Parse '{'.
1289 if (Tok.is(tok::l_brace)) {
1290 (void)ConsumeBrace();
1291 } else {
1292 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1293 << "{"
1294 << ("'=' that follows the context set name \"" +
1295 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1296 .str();
1297 }
1298
1299 llvm::StringMap<SourceLocation> SeenSelectors;
1300 do {
1301 OMPTraitSelector TISelector;
1302 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1303 if (TISelector.Kind != TraitSelector::invalid &&
1304 !TISelector.Properties.empty())
1305 TISet.Selectors.push_back(TISelector);
1306 } while (TryConsumeToken(tok::comma));
1307
1308 // Parse '}'.
1309 if (Tok.is(tok::r_brace)) {
1310 (void)ConsumeBrace();
1311 } else {
1312 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1313 << "}"
1314 << ("context selectors for the context set \"" +
1315 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1316 .str();
1317 }
1318}
1319
1320bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1321 llvm::StringMap<SourceLocation> SeenSets;
1322 do {
1323 OMPTraitSet TISet;
1324 parseOMPContextSelectorSet(TISet, SeenSets);
1325 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1326 TI.Sets.push_back(TISet);
1327 } while (TryConsumeToken(tok::comma));
1328
1329 return false;
1330}
1331
1332void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1333 CachedTokens &Toks,
1334 SourceLocation Loc) {
1335 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1336 PP.EnterToken(Tok, /*IsReinject*/ true);
1337 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1338 /*IsReinject*/ true);
1339 // Consume the previously pushed token.
1340 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1341 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1342
1343 FNContextRAII FnContext(*this, Ptr);
1344 // Parse function declaration id.
1345 SourceLocation RLoc;
1346 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1347 // instead of MemberExprs.
1348 ExprResult AssociatedFunction;
1349 {
1350 // Do not mark function as is used to prevent its emission if this is the
1351 // only place where it is used.
1352 EnterExpressionEvaluationContext Unevaluated(
1354 AssociatedFunction = ParseOpenMPParensExpr(
1355 getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion), RLoc,
1356 /*IsAddressOfOperand=*/true);
1357 }
1358 if (!AssociatedFunction.isUsable()) {
1359 if (!Tok.is(tok::annot_pragma_openmp_end))
1360 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1361 ;
1362 // Skip the last annot_pragma_openmp_end.
1363 (void)ConsumeAnnotationToken();
1364 return;
1365 }
1366
1367 OMPTraitInfo *ParentTI =
1368 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
1369 ASTContext &ASTCtx = Actions.getASTContext();
1370 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1371 SmallVector<Expr *, 6> AdjustNothing;
1372 SmallVector<Expr *, 6> AdjustNeedDevicePtr;
1373 SmallVector<Expr *, 6> AdjustNeedDeviceAddr;
1374 SmallVector<OMPInteropInfo, 3> AppendArgs;
1375 SourceLocation AdjustArgsLoc, AppendArgsLoc;
1376
1377 // At least one clause is required.
1378 if (Tok.is(tok::annot_pragma_openmp_end)) {
1379 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1380 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1381 }
1382
1383 bool IsError = false;
1384 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1385 OpenMPClauseKind CKind = Tok.isAnnotation()
1386 ? OMPC_unknown
1387 : getOpenMPClauseKind(PP.getSpelling(Tok));
1388 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
1389 getLangOpts().OpenMP)) {
1390 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1391 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1392 IsError = true;
1393 }
1394 if (!IsError) {
1395 switch (CKind) {
1396 case OMPC_match:
1397 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
1398 break;
1399 case OMPC_adjust_args: {
1400 AdjustArgsLoc = Tok.getLocation();
1401 ConsumeToken();
1402 SemaOpenMP::OpenMPVarListDataTy Data;
1403 SmallVector<Expr *> Vars;
1404 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
1405 Vars, Data);
1406 if (!IsError) {
1407 switch (Data.ExtraModifier) {
1408 case OMPC_ADJUST_ARGS_nothing:
1409 llvm::append_range(AdjustNothing, Vars);
1410 break;
1411 case OMPC_ADJUST_ARGS_need_device_ptr:
1412 llvm::append_range(AdjustNeedDevicePtr, Vars);
1413 break;
1414 case OMPC_ADJUST_ARGS_need_device_addr:
1415 llvm::append_range(AdjustNeedDeviceAddr, Vars);
1416 break;
1417 default:
1418 llvm_unreachable("Unexpected 'adjust_args' clause modifier.");
1419 }
1420 }
1421 break;
1422 }
1423 case OMPC_append_args:
1424 if (!AppendArgs.empty()) {
1425 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1426 << getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion)
1427 << getOpenMPClauseName(CKind) << 0;
1428 IsError = true;
1429 }
1430 if (!IsError) {
1431 AppendArgsLoc = Tok.getLocation();
1432 ConsumeToken();
1433 IsError = parseOpenMPAppendArgs(AppendArgs);
1434 }
1435 break;
1436 default:
1437 llvm_unreachable("Unexpected clause for declare variant.");
1438 }
1439 }
1440 if (IsError) {
1441 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1442 ;
1443 // Skip the last annot_pragma_openmp_end.
1444 (void)ConsumeAnnotationToken();
1445 return;
1446 }
1447 // Skip ',' if any.
1448 if (Tok.is(tok::comma))
1449 ConsumeToken();
1450 }
1451
1452 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1453 Actions.OpenMP().checkOpenMPDeclareVariantFunction(
1454 Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
1455 SourceRange(Loc, Tok.getLocation()));
1456
1457 if (DeclVarData && !TI.Sets.empty())
1458 Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(
1459 DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1460 AdjustNeedDevicePtr, AdjustNeedDeviceAddr, AppendArgs, AdjustArgsLoc,
1461 AppendArgsLoc, SourceRange(Loc, Tok.getLocation()));
1462
1463 // Skip the last annot_pragma_openmp_end.
1464 (void)ConsumeAnnotationToken();
1465}
1466
1467bool Parser::parseOpenMPAppendArgs(
1468 SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
1469 bool HasError = false;
1470 // Parse '('.
1471 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1472 if (T.expectAndConsume(diag::err_expected_lparen_after,
1473 getOpenMPClauseName(OMPC_append_args).data()))
1474 return true;
1475
1476 // Parse the list of append-ops, each is;
1477 // interop(interop-type[,interop-type]...)
1478 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
1479 ConsumeToken();
1480 BalancedDelimiterTracker IT(*this, tok::l_paren,
1481 tok::annot_pragma_openmp_end);
1482 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
1483 return true;
1484
1485 OMPInteropInfo InteropInfo;
1486 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1487 HasError = true;
1488 else
1489 InteropInfos.push_back(InteropInfo);
1490
1491 IT.consumeClose();
1492 if (Tok.is(tok::comma))
1493 ConsumeToken();
1494 }
1495 if (!HasError && InteropInfos.empty()) {
1496 HasError = true;
1497 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
1498 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1500 }
1501 HasError = T.consumeClose() || HasError;
1502 return HasError;
1503}
1504
1505bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1506 OMPTraitInfo &TI,
1507 OMPTraitInfo *ParentTI) {
1508 // Parse 'match'.
1509 OpenMPClauseKind CKind = Tok.isAnnotation()
1510 ? OMPC_unknown
1511 : getOpenMPClauseKind(PP.getSpelling(Tok));
1512 if (CKind != OMPC_match) {
1513 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1514 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1515 return true;
1516 }
1517 (void)ConsumeToken();
1518 // Parse '('.
1519 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1520 if (T.expectAndConsume(diag::err_expected_lparen_after,
1521 getOpenMPClauseName(OMPC_match).data()))
1522 return true;
1523
1524 // Parse inner context selectors.
1525 parseOMPContextSelectors(Loc, TI);
1526
1527 // Parse ')'
1528 (void)T.consumeClose();
1529
1530 if (!ParentTI)
1531 return false;
1532
1533 // Merge the parent/outer trait info into the one we just parsed and diagnose
1534 // problems.
1535 // TODO: Keep some source location in the TI to provide better diagnostics.
1536 // TODO: Perform some kind of equivalence check on the condition and score
1537 // expressions.
1538 for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1539 bool MergedSet = false;
1540 for (OMPTraitSet &Set : TI.Sets) {
1541 if (Set.Kind != ParentSet.Kind)
1542 continue;
1543 MergedSet = true;
1544 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1545 bool MergedSelector = false;
1546 for (OMPTraitSelector &Selector : Set.Selectors) {
1547 if (Selector.Kind != ParentSelector.Kind)
1548 continue;
1549 MergedSelector = true;
1550 for (const OMPTraitProperty &ParentProperty :
1551 ParentSelector.Properties) {
1552 bool MergedProperty = false;
1553 for (OMPTraitProperty &Property : Selector.Properties) {
1554 // Ignore "equivalent" properties.
1555 if (Property.Kind != ParentProperty.Kind)
1556 continue;
1557
1558 // If the kind is the same but the raw string not, we don't want
1559 // to skip out on the property.
1560 MergedProperty |= Property.RawString == ParentProperty.RawString;
1561
1562 if (Property.RawString == ParentProperty.RawString &&
1563 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1564 continue;
1565
1566 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1567 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1568 } else if (Selector.ScoreOrCondition !=
1569 ParentSelector.ScoreOrCondition) {
1570 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1571 << getOpenMPContextTraitPropertyName(
1572 ParentProperty.Kind, ParentProperty.RawString)
1573 << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1574 << getOpenMPContextTraitSetName(ParentSet.Kind);
1575 }
1576 }
1577 if (!MergedProperty)
1578 Selector.Properties.push_back(ParentProperty);
1579 }
1580 }
1581 if (!MergedSelector)
1582 Set.Selectors.push_back(ParentSelector);
1583 }
1584 }
1585 if (!MergedSet)
1586 TI.Sets.push_back(ParentSet);
1587 }
1588
1589 return false;
1590}
1591
1592void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
1594 SourceLocation Loc) {
1595 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
1596 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1597 OpenMPClauseKind CKind = Tok.isAnnotation()
1598 ? OMPC_unknown
1599 : getOpenMPClauseKind(PP.getSpelling(Tok));
1600 Actions.OpenMP().StartOpenMPClause(CKind);
1601 OMPClause *Clause =
1602 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
1603 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1605 SeenClauses[unsigned(CKind)] = true;
1606 if (Clause != nullptr)
1607 Clauses.push_back(Clause);
1608 if (Tok.is(tok::annot_pragma_openmp_end)) {
1609 Actions.OpenMP().EndOpenMPClause();
1610 break;
1611 }
1612 // Skip ',' if any.
1613 if (Tok.is(tok::comma))
1614 ConsumeToken();
1615 Actions.OpenMP().EndOpenMPClause();
1616 }
1617}
1618
1619void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
1620 SourceLocation Loc) {
1621 SmallVector<std::string, 4> Assumptions;
1622 bool SkippedClauses = false;
1623
1624 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
1625 BalancedDelimiterTracker T(*this, tok::l_paren,
1626 tok::annot_pragma_openmp_end);
1627 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1628 return;
1629 T.skipToEnd();
1630 if (IssueNote && T.getCloseLocation().isValid())
1631 Diag(T.getCloseLocation(),
1632 diag::note_omp_assumption_clause_continue_here);
1633 };
1634
1635 /// Helper to determine which AssumptionClauseMapping (ACM) in the
1636 /// AssumptionClauseMappings table matches \p RawString. The return value is
1637 /// the index of the matching ACM into the table or -1 if there was no match.
1638 auto MatchACMClause = [&](StringRef RawString) {
1639 llvm::StringSwitch<int> SS(RawString);
1640 unsigned ACMIdx = 0;
1641 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1642 if (ACMI.StartsWith)
1643 SS.StartsWith(ACMI.Identifier, ACMIdx++);
1644 else
1645 SS.Case(ACMI.Identifier, ACMIdx++);
1646 }
1647 return SS.Default(-1);
1648 };
1649
1650 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1651 IdentifierInfo *II = nullptr;
1652 SourceLocation StartLoc = Tok.getLocation();
1653 int Idx = -1;
1654 if (Tok.isAnyIdentifier()) {
1655 II = Tok.getIdentifierInfo();
1656 Idx = MatchACMClause(II->getName());
1657 }
1659
1660 bool NextIsLPar = Tok.is(tok::l_paren);
1661 // Handle unknown clauses by skipping them.
1662 if (Idx == -1) {
1663 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1664 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1665 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion)
1666 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1667 if (NextIsLPar)
1668 SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
1669 SkippedClauses = true;
1670 continue;
1671 }
1672 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1673 if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1674 // TODO: We ignore absent, contains, and holds assumptions for now. We
1675 // also do not verify the content in the parenthesis at all.
1676 SkippedClauses = true;
1677 SkipBraces(II->getName(), /* IssueNote */ false);
1678 continue;
1679 }
1680
1681 if (NextIsLPar) {
1682 Diag(Tok.getLocation(),
1683 diag::warn_omp_unknown_assumption_clause_without_args)
1684 << II;
1685 SkipBraces(II->getName(), /* IssueNote */ true);
1686 }
1687
1688 assert(II && "Expected an identifier clause!");
1689 std::string Assumption = II->getName().str();
1690 if (ACMI.StartsWith)
1691 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
1692 else
1693 Assumption = "omp_" + Assumption;
1694 Assumptions.push_back(Assumption);
1695 }
1696
1697 Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
1698 SkippedClauses);
1699}
1700
1701void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
1702 if (Actions.OpenMP().isInOpenMPAssumeScope())
1703 Actions.OpenMP().ActOnOpenMPEndAssumesDirective();
1704 else
1705 Diag(Loc, diag::err_expected_begin_assumes);
1706}
1707
1708/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1709///
1710/// default-clause:
1711/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')
1712///
1713/// proc_bind-clause:
1714/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1715///
1716/// device_type-clause:
1717/// 'device_type' '(' 'host' | 'nohost' | 'any' )'
1718namespace {
1719struct SimpleClauseData {
1720 unsigned Type;
1721 SourceLocation Loc;
1722 SourceLocation LOpen;
1723 SourceLocation TypeLoc;
1724 SourceLocation RLoc;
1725 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1726 SourceLocation TypeLoc, SourceLocation RLoc)
1727 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1728};
1729} // anonymous namespace
1730
1731static std::optional<SimpleClauseData>
1733 const Token &Tok = P.getCurToken();
1734 SourceLocation Loc = Tok.getLocation();
1735 SourceLocation LOpen = P.ConsumeToken();
1736 // Parse '('.
1737 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1738 if (T.expectAndConsume(diag::err_expected_lparen_after,
1739 getOpenMPClauseName(Kind).data()))
1740 return std::nullopt;
1741
1743 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1744 P.getLangOpts());
1745 SourceLocation TypeLoc = Tok.getLocation();
1746 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1747 Tok.isNot(tok::annot_pragma_openmp_end))
1748 P.ConsumeAnyToken();
1749
1750 // Parse ')'.
1751 SourceLocation RLoc = Tok.getLocation();
1752 if (!T.consumeClose())
1753 RLoc = T.getCloseLocation();
1754
1755 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1756}
1757
1758void Parser::ParseOMPDeclareTargetClauses(
1760 SourceLocation DeviceTypeLoc;
1761 bool RequiresToLinkLocalOrIndirectClause = false;
1762 bool HasToLinkLocalOrIndirectClause = false;
1763 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1764 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1765 bool HasIdentifier = Tok.is(tok::identifier);
1766 if (HasIdentifier) {
1767 // If we see any clause we need a to, link, or local clause.
1768 RequiresToLinkLocalOrIndirectClause = true;
1769 IdentifierInfo *II = Tok.getIdentifierInfo();
1770 StringRef ClauseName = II->getName();
1771 bool IsDeviceTypeClause =
1772 getLangOpts().OpenMP >= 50 &&
1773 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1774
1775 bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1776 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1777
1778 if (DTCI.Indirect && IsIndirectClause) {
1779 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1780 Diag(Tok, diag::err_omp_more_one_clause)
1781 << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)
1782 << getOpenMPClauseName(OMPC_indirect) << 0;
1783 break;
1784 }
1785 bool IsToEnterLinkOrLocalClause =
1786 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1787 assert((!IsDeviceTypeClause || !IsToEnterLinkOrLocalClause) &&
1788 "Cannot be both!");
1789
1790 // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1791 // `enter` clause.
1792 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1793 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1794 break;
1795 }
1796 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1797 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1798 break;
1799 }
1800
1801 // The 'local' clause is only available in OpenMP 6.0.
1802 if (getLangOpts().OpenMP < 60 && ClauseName == "local") {
1803 Diag(Tok, getLangOpts().OpenMP >= 52
1804 ? diag::err_omp_declare_target_unexpected_clause_52
1805 : diag::err_omp_declare_target_unexpected_clause)
1806 << ClauseName
1807 << (getLangOpts().OpenMP >= 51 ? 4
1808 : getLangOpts().OpenMP >= 50 ? 2
1809 : 1);
1810 break;
1811 }
1812
1813 if (!IsDeviceTypeClause && !IsIndirectClause &&
1814 DTCI.Kind == OMPD_begin_declare_target) {
1815 Diag(Tok, getLangOpts().OpenMP >= 52
1816 ? diag::err_omp_declare_target_unexpected_clause_52
1817 : diag::err_omp_declare_target_unexpected_clause)
1818 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
1819 break;
1820 }
1821
1822 if (!IsDeviceTypeClause && !IsToEnterLinkOrLocalClause &&
1823 !IsIndirectClause) {
1824 Diag(Tok, getLangOpts().OpenMP >= 52
1825 ? diag::err_omp_declare_target_unexpected_clause_52
1826 : diag::err_omp_declare_target_unexpected_clause)
1827 << ClauseName
1828 << (getLangOpts().OpenMP > 52 ? 5
1829 : getLangOpts().OpenMP >= 51 ? 4
1830 : getLangOpts().OpenMP >= 50 ? 2
1831 : 1);
1832 break;
1833 }
1834
1835 if (IsToEnterLinkOrLocalClause || IsIndirectClause)
1836 HasToLinkLocalOrIndirectClause = true;
1837
1838 if (IsIndirectClause) {
1839 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1840 break;
1841 continue;
1842 }
1843 // Parse 'device_type' clause and go to next clause if any.
1844 if (IsDeviceTypeClause) {
1845 std::optional<SimpleClauseData> DevTypeData =
1846 parseOpenMPSimpleClause(*this, OMPC_device_type);
1847 if (DevTypeData) {
1848 if (DeviceTypeLoc.isValid()) {
1849 // We already saw another device_type clause, diagnose it.
1850 Diag(DevTypeData->Loc,
1851 diag::warn_omp_more_one_device_type_clause);
1852 break;
1853 }
1854 switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1855 case OMPC_DEVICE_TYPE_any:
1856 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1857 break;
1858 case OMPC_DEVICE_TYPE_host:
1859 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1860 break;
1861 case OMPC_DEVICE_TYPE_nohost:
1862 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1863 break;
1865 llvm_unreachable("Unexpected device_type");
1866 }
1867 DeviceTypeLoc = DevTypeData->Loc;
1868 }
1869 continue;
1870 }
1871 ConsumeToken();
1872 }
1873
1874 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1875 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1876 DeclarationNameInfo NameInfo) {
1877 NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
1878 getCurScope(), SS, NameInfo);
1879 if (!ND)
1880 return;
1881 SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
1882 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1883 if (!FirstMapping)
1884 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1885 << NameInfo.getName();
1886 };
1887 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1888 /*AllowScopeSpecifier=*/true))
1889 break;
1890 }
1891
1892 if (Tok.is(tok::l_paren)) {
1893 Diag(Tok,
1894 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1895 break;
1896 }
1897 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1898 Diag(Tok,
1899 getLangOpts().OpenMP >= 52
1900 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1901 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1902 break;
1903 }
1904
1905 // Consume optional ','.
1906 if (Tok.is(tok::comma))
1907 ConsumeToken();
1908 }
1909
1910 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1911 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1912
1913 // declare target requires at least one clause.
1914 if (DTCI.Kind == OMPD_declare_target && RequiresToLinkLocalOrIndirectClause &&
1915 !HasToLinkLocalOrIndirectClause)
1916 Diag(DTCI.Loc, diag::err_omp_declare_target_missing_required_clause)
1917 << (getLangOpts().OpenMP >= 60 ? 3
1918 : getLangOpts().OpenMP == 52 ? 2
1919 : getLangOpts().OpenMP == 51 ? 1
1920 : 0);
1921
1922 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1923}
1924
1925void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1926 // The last seen token is annot_pragma_openmp_end - need to check for
1927 // extra tokens.
1928 if (Tok.is(tok::annot_pragma_openmp_end))
1929 return;
1930
1931 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1932 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1933 << getOpenMPDirectiveName(DKind, OMPVersion);
1934 while (Tok.isNot(tok::annot_pragma_openmp_end))
1936}
1937
1938void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1939 OpenMPDirectiveKind ExpectedKind,
1940 OpenMPDirectiveKind FoundKind,
1941 SourceLocation BeginLoc,
1942 SourceLocation FoundLoc,
1943 bool SkipUntilOpenMPEnd) {
1944 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1945
1946 if (FoundKind == ExpectedKind) {
1948 skipUntilPragmaOpenMPEnd(ExpectedKind);
1949 return;
1950 }
1951
1952 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1953 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1954 << DiagSelection;
1955 Diag(BeginLoc, diag::note_matching)
1956 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + "'")
1957 .str();
1958 if (SkipUntilOpenMPEnd)
1959 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1960}
1961
1962void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
1963 OpenMPDirectiveKind EndDKind,
1964 SourceLocation DKLoc) {
1965 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
1966 Tok.getLocation(),
1967 /* SkipUntilOpenMPEnd */ false);
1968 // Skip the last annot_pragma_openmp_end.
1969 if (Tok.is(tok::annot_pragma_openmp_end))
1970 ConsumeAnnotationToken();
1971}
1972
1973Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1974 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
1975 DeclSpec::TST TagType, Decl *Tag) {
1976 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
1977 "Not an OpenMP directive!");
1978 ParsingOpenMPDirectiveRAII DirScope(*this);
1979 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1980 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1981
1982 SourceLocation Loc;
1983 OpenMPDirectiveKind DKind;
1984 if (Delayed) {
1985 TentativeParsingAction TPA(*this);
1986 Loc = ConsumeAnnotationToken();
1987 DKind = parseOpenMPDirectiveKind(*this);
1988 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1989 // Need to delay parsing until completion of the parent class.
1990 TPA.Revert();
1991 CachedTokens Toks;
1992 unsigned Cnt = 1;
1993 Toks.push_back(Tok);
1994 while (Cnt && Tok.isNot(tok::eof)) {
1995 (void)ConsumeAnyToken();
1996 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
1997 ++Cnt;
1998 else if (Tok.is(tok::annot_pragma_openmp_end))
1999 --Cnt;
2000 Toks.push_back(Tok);
2001 }
2002 // Skip last annot_pragma_openmp_end.
2003 if (Cnt == 0)
2004 (void)ConsumeAnyToken();
2005 auto *LP = new LateParsedPragma(this, AS);
2006 LP->takeToks(Toks);
2007 getCurrentClass().LateParsedDeclarations.push_back(LP);
2008 return nullptr;
2009 }
2010 TPA.Commit();
2011 } else {
2012 Loc = ConsumeAnnotationToken();
2013 DKind = parseOpenMPDirectiveKind(*this);
2014 }
2015
2016 switch (DKind) {
2017 case OMPD_threadprivate: {
2018 ConsumeToken();
2019 DeclDirectiveListParserHelper Helper(this, DKind);
2020 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2021 /*AllowScopeSpecifier=*/true)) {
2022 skipUntilPragmaOpenMPEnd(DKind);
2023 // Skip the last annot_pragma_openmp_end.
2024 ConsumeAnnotationToken();
2025 return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2026 Loc, Helper.getIdentifiers());
2027 }
2028 break;
2029 }
2030 case OMPD_groupprivate: {
2031 ConsumeToken();
2032 DeclDirectiveListParserHelper Helper(this, DKind);
2033 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2034 /*AllowScopeSpecifier=*/true)) {
2035 skipUntilPragmaOpenMPEnd(DKind);
2036 // Skip the last annot_pragma_openmp_end.
2037 ConsumeAnnotationToken();
2038 return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2039 Loc, Helper.getIdentifiers());
2040 }
2041 break;
2042 }
2043 case OMPD_allocate: {
2044 ConsumeToken();
2045 DeclDirectiveListParserHelper Helper(this, DKind);
2046 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2047 /*AllowScopeSpecifier=*/true)) {
2048 SmallVector<OMPClause *, 1> Clauses;
2049 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2050 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
2051 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2052 OpenMPClauseKind CKind =
2053 Tok.isAnnotation() ? OMPC_unknown
2054 : getOpenMPClauseKind(PP.getSpelling(Tok));
2055 Actions.OpenMP().StartOpenMPClause(CKind);
2056 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2057 !SeenClauses[unsigned(CKind)]);
2058 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2060 SeenClauses[unsigned(CKind)] = true;
2061 if (Clause != nullptr)
2062 Clauses.push_back(Clause);
2063 if (Tok.is(tok::annot_pragma_openmp_end)) {
2064 Actions.OpenMP().EndOpenMPClause();
2065 break;
2066 }
2067 // Skip ',' if any.
2068 if (Tok.is(tok::comma))
2069 ConsumeToken();
2070 Actions.OpenMP().EndOpenMPClause();
2071 }
2072 skipUntilPragmaOpenMPEnd(DKind);
2073 }
2074 // Skip the last annot_pragma_openmp_end.
2075 ConsumeAnnotationToken();
2076 return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2077 Loc, Helper.getIdentifiers(), Clauses);
2078 }
2079 break;
2080 }
2081 case OMPD_requires: {
2082 SourceLocation StartLoc = ConsumeToken();
2083 SmallVector<OMPClause *, 5> Clauses;
2084 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2085 if (Tok.is(tok::annot_pragma_openmp_end)) {
2086 Diag(Tok, diag::err_omp_expected_clause)
2087 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2088 break;
2089 }
2090 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2091 OpenMPClauseKind CKind = Tok.isAnnotation()
2092 ? OMPC_unknown
2093 : getOpenMPClauseKind(PP.getSpelling(Tok));
2094 Actions.OpenMP().StartOpenMPClause(CKind);
2095 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
2096 !SeenClauses[unsigned(CKind)]);
2097 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2099 SeenClauses[unsigned(CKind)] = true;
2100 if (Clause != nullptr)
2101 Clauses.push_back(Clause);
2102 if (Tok.is(tok::annot_pragma_openmp_end)) {
2103 Actions.OpenMP().EndOpenMPClause();
2104 break;
2105 }
2106 // Skip ',' if any.
2107 if (Tok.is(tok::comma))
2108 ConsumeToken();
2109 Actions.OpenMP().EndOpenMPClause();
2110 }
2111 // Consume final annot_pragma_openmp_end
2112 if (Clauses.empty()) {
2113 Diag(Tok, diag::err_omp_expected_clause)
2114 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2115 ConsumeAnnotationToken();
2116 return nullptr;
2117 }
2118 ConsumeAnnotationToken();
2119 return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
2120 }
2121 case OMPD_error: {
2122 SmallVector<OMPClause *, 1> Clauses;
2123 SourceLocation StartLoc = ConsumeToken();
2124 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2125 Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2126 SourceLocation(),
2127 /*InExContext = */ false);
2128 break;
2129 }
2130 case OMPD_assumes:
2131 case OMPD_begin_assumes:
2132 ParseOpenMPAssumesDirective(DKind, ConsumeToken());
2133 break;
2134 case OMPD_end_assumes:
2135 ParseOpenMPEndAssumesDirective(ConsumeToken());
2136 break;
2137 case OMPD_declare_reduction:
2138 ConsumeToken();
2139 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2140 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2141 // Skip the last annot_pragma_openmp_end.
2142 ConsumeAnnotationToken();
2143 return Res;
2144 }
2145 break;
2146 case OMPD_declare_mapper: {
2147 ConsumeToken();
2148 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2149 // Skip the last annot_pragma_openmp_end.
2150 ConsumeAnnotationToken();
2151 return Res;
2152 }
2153 break;
2154 }
2155 case OMPD_begin_declare_variant: {
2156 ConsumeToken();
2158 // Skip the last annot_pragma_openmp_end.
2159 if (!isEofOrEom())
2160 ConsumeAnnotationToken();
2161 }
2162 return nullptr;
2163 }
2164 case OMPD_end_declare_variant: {
2165 ConsumeToken();
2166 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2167 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2168 else
2169 Diag(Loc, diag::err_expected_begin_declare_variant);
2170 // Skip the last annot_pragma_openmp_end.
2171 ConsumeAnnotationToken();
2172 return nullptr;
2173 }
2174 case OMPD_declare_variant:
2175 case OMPD_declare_simd: {
2176 // The syntax is:
2177 // { #pragma omp declare {simd|variant} }
2178 // <function-declaration-or-definition>
2179 //
2180 CachedTokens Toks;
2181 Toks.push_back(Tok);
2182 ConsumeToken();
2183 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2184 Toks.push_back(Tok);
2186 }
2187 Toks.push_back(Tok);
2189
2190 DeclGroupPtrTy Ptr;
2191 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2192 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2193 TagType, Tag);
2194 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
2195 // Here we expect to see some function declaration.
2196 if (AS == AS_none) {
2197 assert(TagType == DeclSpec::TST_unspecified);
2198 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2199 MaybeParseCXX11Attributes(Attrs);
2200 ParsingDeclSpec PDS(*this);
2201 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2202 } else {
2203 Ptr =
2204 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
2205 }
2206 }
2207 if (!Ptr) {
2208 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2209 << (DKind == OMPD_declare_simd ? 0 : 1);
2210 return DeclGroupPtrTy();
2211 }
2212 if (DKind == OMPD_declare_simd)
2213 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2214 assert(DKind == OMPD_declare_variant &&
2215 "Expected declare variant directive only");
2216 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2217 return Ptr;
2218 }
2219 case OMPD_begin_declare_target:
2220 case OMPD_declare_target: {
2221 SourceLocation DTLoc = ConsumeAnyToken();
2222 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2223 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2224 if (DKind == OMPD_declare_target && !HasClauses &&
2225 getLangOpts().OpenMP >= 52)
2226 Diag(DTLoc, diag::warn_omp_deprecated_declare_target_delimited_form);
2227 if (HasClauses)
2228 ParseOMPDeclareTargetClauses(DTCI);
2229 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2230 !HasClauses ||
2231 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2232
2233 // Skip the last annot_pragma_openmp_end.
2235
2236 if (HasImplicitMappings) {
2237 Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
2238 return nullptr;
2239 }
2240
2241 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2242 llvm::SmallVector<Decl *, 4> Decls;
2243 for (auto &It : DTCI.ExplicitlyMapped)
2244 Decls.push_back(It.first);
2245 return Actions.BuildDeclaratorGroup(Decls);
2246 }
2247 case OMPD_end_declare_target: {
2248 if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2249 Diag(Tok, diag::err_omp_unexpected_directive)
2250 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2251 break;
2252 }
2253 const SemaOpenMP::DeclareTargetContextInfo &DTCI =
2254 Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
2255 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2256 return nullptr;
2257 }
2258 case OMPD_assume: {
2259 Diag(Tok, diag::err_omp_unexpected_directive)
2260 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2261 break;
2262 }
2263 case OMPD_unknown:
2264 Diag(Tok, diag::err_omp_unknown_directive);
2265 break;
2266 default:
2267 switch (getDirectiveCategory(DKind)) {
2268 case Category::Executable:
2269 case Category::Meta:
2270 case Category::Subsidiary:
2271 case Category::Utility:
2272 Diag(Tok, diag::err_omp_unexpected_directive)
2273 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2274 break;
2275 case Category::Declarative:
2276 case Category::Informational:
2277 break;
2278 }
2279 }
2280 while (Tok.isNot(tok::annot_pragma_openmp_end))
2283 return nullptr;
2284}
2285
2286StmtResult Parser::ParseOpenMPExecutableDirective(
2287 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2288 bool ReadDirectiveWithinMetadirective) {
2289 assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2290 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2291
2292 bool HasAssociatedStatement = true;
2293 Association Assoc = getDirectiveAssociation(DKind);
2294
2295 // OMPD_ordered has None as association, but it comes in two variants,
2296 // the second of which is associated with a block.
2297 // OMPD_scan and OMPD_section are both "separating", but section is treated
2298 // as if it was associated with a statement, while scan is not.
2299 if (DKind != OMPD_ordered && DKind != OMPD_section &&
2300 (Assoc == Association::None || Assoc == Association::Separating)) {
2301 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2302 ParsedStmtContext()) {
2303 Diag(Tok, diag::err_omp_immediate_directive)
2304 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2305 if (DKind == OMPD_error) {
2306 SkipUntil(tok::annot_pragma_openmp_end);
2307 return StmtError();
2308 }
2309 }
2310 HasAssociatedStatement = false;
2311 }
2312
2313 SourceLocation EndLoc;
2314 SmallVector<OMPClause *, 5> Clauses;
2315 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2316 DeclarationNameInfo DirName;
2317 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2318 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2320
2321 // Special processing for flush and depobj clauses.
2322 Token ImplicitTok;
2323 bool ImplicitClauseAllowed = false;
2324 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2325 ImplicitTok = Tok;
2326 ImplicitClauseAllowed = true;
2327 }
2328 ConsumeToken();
2329 // Parse directive name of the 'critical' directive if any.
2330 if (DKind == OMPD_critical) {
2331 BalancedDelimiterTracker T(*this, tok::l_paren,
2332 tok::annot_pragma_openmp_end);
2333 if (!T.consumeOpen()) {
2334 if (Tok.isAnyIdentifier()) {
2335 DirName =
2336 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2338 } else {
2339 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2340 }
2341 T.consumeClose();
2342 }
2343 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2344 CancelRegion = parseOpenMPDirectiveKind(*this);
2345 if (Tok.isNot(tok::annot_pragma_openmp_end))
2347 }
2348
2349 if (isOpenMPLoopDirective(DKind))
2350 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2351 if (isOpenMPSimdDirective(DKind))
2352 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2353 ParseScope OMPDirectiveScope(this, ScopeFlags);
2354 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2355 Loc);
2356
2357 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2358 // If we are parsing for a directive within a metadirective, the directive
2359 // ends with a ')'.
2360 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2361 while (Tok.isNot(tok::annot_pragma_openmp_end))
2363 break;
2364 }
2365 bool HasImplicitClause = false;
2366 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2367 HasImplicitClause = true;
2368 // Push copy of the current token back to stream to properly parse
2369 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2370 PP.EnterToken(Tok, /*IsReinject*/ true);
2371 PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2373 }
2374 OpenMPClauseKind CKind = Tok.isAnnotation()
2375 ? OMPC_unknown
2376 : getOpenMPClauseKind(PP.getSpelling(Tok));
2377 if (HasImplicitClause) {
2378 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2379 if (DKind == OMPD_flush) {
2380 CKind = OMPC_flush;
2381 } else {
2382 assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2383 CKind = OMPC_depobj;
2384 }
2385 }
2386 // No more implicit clauses allowed.
2387 ImplicitClauseAllowed = false;
2388 Actions.OpenMP().StartOpenMPClause(CKind);
2389 HasImplicitClause = false;
2390 SourceLocation ClauseLoc = Tok.getLocation();
2391
2392 OMPClause *Clause =
2393 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2394 SeenClauses[unsigned(CKind)] = true;
2395 if (Clause)
2396 Clauses.push_back(Clause);
2397
2398 // Skip ',' if any.
2399 if (Tok.is(tok::comma))
2400 ConsumeToken();
2401 Actions.OpenMP().EndOpenMPClause();
2402
2403 // If ParseOpenMPClause returned without consuming any tokens, skip
2404 // to end to avoid an infinite loop.
2405 if (Tok.getLocation() == ClauseLoc) {
2406 skipUntilPragmaOpenMPEnd(DKind);
2407 break;
2408 }
2409 }
2410 // End location of the directive.
2411 EndLoc = Tok.getLocation();
2412 // Consume final annot_pragma_openmp_end.
2413 ConsumeAnnotationToken();
2414
2415 if (DKind == OMPD_ordered) {
2416 // If the depend or doacross clause is specified, the ordered construct
2417 // is a stand-alone directive.
2418 for (auto CK : {OMPC_depend, OMPC_doacross}) {
2419 if (SeenClauses[unsigned(CK)]) {
2420 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2421 ParsedStmtContext()) {
2422 Diag(Loc, diag::err_omp_immediate_directive)
2423 << getOpenMPDirectiveName(DKind, OMPVersion) << 1
2424 << getOpenMPClauseName(CK);
2425 }
2426 HasAssociatedStatement = false;
2427 }
2428 }
2429 }
2430
2431 if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
2432 !SeenClauses[unsigned(OMPC_sizes)]) {
2433 Diag(Loc, diag::err_omp_required_clause)
2434 << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";
2435 }
2436 if (DKind == OMPD_split && !SeenClauses[unsigned(OMPC_counts)]) {
2437 Diag(Loc, diag::err_omp_required_clause)
2438 << getOpenMPDirectiveName(DKind, OMPVersion) << "counts";
2439 }
2440
2441 StmtResult AssociatedStmt;
2442 if (HasAssociatedStatement) {
2443 // The body is a block scope like in Lambdas and Blocks.
2444 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2445 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2446 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2447 // should have at least one compound statement scope within it.
2448 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2449 {
2450 Sema::CompoundScopeRAII Scope(Actions);
2451 AssociatedStmt = ParseStatement();
2452
2453 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2454 getLangOpts().OpenMPIRBuilder)
2455 AssociatedStmt =
2456 Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2457 }
2458 AssociatedStmt =
2459 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2460 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2461 DKind == OMPD_target_exit_data) {
2462 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2463 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2464 Actions.ActOnCompoundStmt(Loc, Loc, {},
2465 /*isStmtExpr=*/false));
2466 AssociatedStmt =
2467 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2468 }
2469
2470 StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
2471 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2472
2473 // Exit scope.
2474 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2475 OMPDirectiveScope.Exit();
2476
2477 return Directive;
2478}
2479
2480StmtResult Parser::ParseOpenMPInformationalDirective(
2481 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2482 bool ReadDirectiveWithinMetadirective) {
2483 assert(isOpenMPInformationalDirective(DKind) &&
2484 "Unexpected directive category");
2485
2486 bool HasAssociatedStatement = true;
2487
2488 SmallVector<OMPClause *, 5> Clauses;
2489 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2490 DeclarationNameInfo DirName;
2491 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2493 ParseScope OMPDirectiveScope(this, ScopeFlags);
2494
2495 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2496 Loc);
2497
2498 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2499 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2500 while (Tok.isNot(tok::annot_pragma_openmp_end))
2502 break;
2503 }
2504
2505 OpenMPClauseKind CKind = Tok.isAnnotation()
2506 ? OMPC_unknown
2507 : getOpenMPClauseKind(PP.getSpelling(Tok));
2508 Actions.OpenMP().StartOpenMPClause(CKind);
2509 OMPClause *Clause =
2510 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2511 SeenClauses[unsigned(CKind)] = true;
2512 if (Clause)
2513 Clauses.push_back(Clause);
2514
2515 if (Tok.is(tok::comma))
2516 ConsumeToken();
2517 Actions.OpenMP().EndOpenMPClause();
2518 }
2519
2520 SourceLocation EndLoc = Tok.getLocation();
2521 ConsumeAnnotationToken();
2522
2523 StmtResult AssociatedStmt;
2524 if (HasAssociatedStatement) {
2525 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2526 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2527 {
2528 Sema::CompoundScopeRAII Scope(Actions);
2529 AssociatedStmt = ParseStatement();
2530 }
2531 AssociatedStmt =
2532 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2533 }
2534
2535 StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
2536 DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2537
2538 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2539 OMPDirectiveScope.Exit();
2540
2541 return Directive;
2542}
2543
2544StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2545 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2546 if (!ReadDirectiveWithinMetadirective)
2547 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2548 "Not an OpenMP directive!");
2549 ParsingOpenMPDirectiveRAII DirScope(*this);
2550 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2551 SourceLocation Loc = ReadDirectiveWithinMetadirective
2552 ? Tok.getLocation()
2553 : ConsumeAnnotationToken();
2554 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2556 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2557 Diag(Tok, diag::err_omp_unknown_directive);
2558 return StmtError();
2559 }
2560
2562
2563 bool IsExecutable = [&]() {
2564 if (DKind == OMPD_error) // OMPD_error is handled as executable
2565 return true;
2566 auto Res = getDirectiveCategory(DKind);
2567 return Res == Category::Executable || Res == Category::Subsidiary;
2568 }();
2569
2570 if (IsExecutable) {
2571 Directive = ParseOpenMPExecutableDirective(
2572 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2573 assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2574 return Directive;
2575 }
2576
2577 switch (DKind) {
2578 case OMPD_nothing:
2579 ConsumeToken();
2580 // If we are parsing the directive within a metadirective, the directive
2581 // ends with a ')'.
2582 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
2583 while (Tok.isNot(tok::annot_pragma_openmp_end))
2585 else
2586 skipUntilPragmaOpenMPEnd(DKind);
2587 if (Tok.is(tok::annot_pragma_openmp_end))
2588 ConsumeAnnotationToken();
2589 // return an empty statement
2590 return StmtEmpty();
2591 case OMPD_metadirective: {
2592 ConsumeToken();
2593 SmallVector<VariantMatchInfo, 4> VMIs;
2594
2595 // First iteration of parsing all clauses of metadirective.
2596 // This iteration only parses and collects all context selector ignoring the
2597 // associated directives.
2598 TentativeParsingAction TPA(*this);
2599 ASTContext &ASTContext = Actions.getASTContext();
2600
2601 BalancedDelimiterTracker T(*this, tok::l_paren,
2602 tok::annot_pragma_openmp_end);
2603 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2604 OpenMPClauseKind CKind = Tok.isAnnotation()
2605 ? OMPC_unknown
2606 : getOpenMPClauseKind(PP.getSpelling(Tok));
2607 // Check if the clause is unrecognized.
2608 if (CKind == OMPC_unknown) {
2609 Diag(Tok, diag::err_omp_expected_clause) << "metadirective";
2610 TPA.Revert();
2611 SkipUntil(tok::annot_pragma_openmp_end);
2612 return Directive;
2613 }
2614 if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)
2615 Diag(Tok, diag::err_omp_unexpected_clause)
2616 << getOpenMPClauseName(CKind) << "metadirective";
2617 if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)
2618 Diag(Tok, diag::warn_omp_default_deprecated);
2619
2620 SourceLocation Loc = ConsumeToken();
2621
2622 // Parse '('.
2623 if (T.expectAndConsume(diag::err_expected_lparen_after,
2624 getOpenMPClauseName(CKind).data())) {
2625 TPA.Revert();
2626 SkipUntil(tok::annot_pragma_openmp_end);
2627 return Directive;
2628 }
2629
2630 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2631 if (CKind == OMPC_when) {
2632 // parse and get OMPTraitInfo to pass to the When clause
2633 parseOMPContextSelectors(Loc, TI);
2634 if (TI.Sets.size() == 0) {
2635 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2636 TPA.Commit();
2637 return Directive;
2638 }
2639
2640 // Parse ':'
2641 if (Tok.is(tok::colon))
2643 else {
2644 Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2645 TPA.Commit();
2646 return Directive;
2647 }
2648 }
2649
2650 // Skip Directive for now. We will parse directive in the second iteration
2651 int paren = 0;
2652 while (Tok.isNot(tok::r_paren) || paren != 0) {
2653 if (Tok.is(tok::l_paren))
2654 paren++;
2655 if (Tok.is(tok::r_paren))
2656 paren--;
2657 if (Tok.is(tok::annot_pragma_openmp_end)) {
2658 Diag(Tok, diag::err_omp_expected_punc)
2659 << getOpenMPClauseName(CKind) << 0;
2660 TPA.Commit();
2661 return Directive;
2662 }
2664 }
2665 // Parse ')'
2666 if (Tok.is(tok::r_paren))
2667 T.consumeClose();
2668
2669 VariantMatchInfo VMI;
2670 TI.getAsVariantMatchInfo(ASTContext, VMI);
2671
2672 VMIs.push_back(VMI);
2673 }
2674
2675 TPA.Revert();
2676 // End of the first iteration. Parser is reset to the start of metadirective
2677
2678 std::function<void(StringRef)> DiagUnknownTrait =
2679 [this, Loc](StringRef ISATrait) {
2680 // TODO Track the selector locations in a way that is accessible here
2681 // to improve the diagnostic location.
2682 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2683 };
2684 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2685 /* CurrentFunctionDecl */ nullptr,
2686 ArrayRef<llvm::omp::TraitProperty>(),
2687 Actions.OpenMP().getOpenMPDeviceNum());
2688
2689 // A single match is returned for OpenMP 5.0
2690 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2691
2692 int Idx = 0;
2693 // In OpenMP 5.0 metadirective is either replaced by another directive or
2694 // ignored.
2695 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2696 // found by getBestWhenMatchForContext.
2697 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2698 // OpenMP 5.0 implementation - Skip to the best index found.
2699 if (Idx++ != BestIdx) {
2700 ConsumeToken(); // Consume clause name
2701 T.consumeOpen(); // Consume '('
2702 int paren = 0;
2703 // Skip everything inside the clause
2704 while (Tok.isNot(tok::r_paren) || paren != 0) {
2705 if (Tok.is(tok::l_paren))
2706 paren++;
2707 if (Tok.is(tok::r_paren))
2708 paren--;
2710 }
2711 // Parse ')'
2712 if (Tok.is(tok::r_paren))
2713 T.consumeClose();
2714 continue;
2715 }
2716
2717 OpenMPClauseKind CKind = Tok.isAnnotation()
2718 ? OMPC_unknown
2719 : getOpenMPClauseKind(PP.getSpelling(Tok));
2720 SourceLocation Loc = ConsumeToken();
2721
2722 // Parse '('.
2723 T.consumeOpen();
2724
2725 // Skip ContextSelectors for when clause
2726 if (CKind == OMPC_when) {
2727 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2728 // parse and skip the ContextSelectors
2729 parseOMPContextSelectors(Loc, TI);
2730
2731 // Parse ':'
2733 }
2734
2735 // If no directive is passed, skip in OpenMP 5.0.
2736 // TODO: Generate nothing directive from OpenMP 5.1.
2737 if (Tok.is(tok::r_paren)) {
2738 SkipUntil(tok::annot_pragma_openmp_end);
2739 break;
2740 }
2741
2742 // Parse Directive
2743 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2744 StmtCtx,
2745 /*ReadDirectiveWithinMetadirective=*/true);
2746 break;
2747 }
2748 // If no match is found and no otherwise clause is present, skip
2749 // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
2750 // if one was specified without an associated directive variant.
2751 if (BestIdx == -1 && Idx > 0) {
2752 assert(Tok.is(tok::annot_pragma_openmp_end) &&
2753 "Expecting the end of the pragma here");
2754 ConsumeAnnotationToken();
2755 return StmtEmpty();
2756 }
2757 break;
2758 }
2759 case OMPD_threadprivate: {
2760 // FIXME: Should this be permitted in C++?
2761 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2762 ParsedStmtContext()) {
2763 Diag(Tok, diag::err_omp_immediate_directive)
2764 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2765 }
2766 ConsumeToken();
2767 DeclDirectiveListParserHelper Helper(this, DKind);
2768 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2769 /*AllowScopeSpecifier=*/false)) {
2770 skipUntilPragmaOpenMPEnd(DKind);
2771 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2772 Loc, Helper.getIdentifiers());
2773 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2774 }
2775 SkipUntil(tok::annot_pragma_openmp_end);
2776 break;
2777 }
2778 case OMPD_groupprivate: {
2779 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2780 ParsedStmtContext()) {
2781 Diag(Tok, diag::err_omp_immediate_directive)
2782 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2783 }
2784 ConsumeToken();
2785 DeclDirectiveListParserHelper Helper(this, DKind);
2786 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2787 /*AllowScopeSpecifier=*/false)) {
2788 skipUntilPragmaOpenMPEnd(DKind);
2789 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2790 Loc, Helper.getIdentifiers());
2791 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2792 }
2793 SkipUntil(tok::annot_pragma_openmp_end);
2794 break;
2795 }
2796 case OMPD_allocate: {
2797 // FIXME: Should this be permitted in C++?
2798 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2799 ParsedStmtContext()) {
2800 Diag(Tok, diag::err_omp_immediate_directive)
2801 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2802 }
2803 ConsumeToken();
2804 DeclDirectiveListParserHelper Helper(this, DKind);
2805 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2806 /*AllowScopeSpecifier=*/false)) {
2807 SmallVector<OMPClause *, 1> Clauses;
2808 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2809 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2810 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2811 OpenMPClauseKind CKind =
2812 Tok.isAnnotation() ? OMPC_unknown
2813 : getOpenMPClauseKind(PP.getSpelling(Tok));
2814 Actions.OpenMP().StartOpenMPClause(CKind);
2815 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2816 !SeenClauses[unsigned(CKind)]);
2817 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2819 SeenClauses[unsigned(CKind)] = true;
2820 if (Clause != nullptr)
2821 Clauses.push_back(Clause);
2822 if (Tok.is(tok::annot_pragma_openmp_end)) {
2823 Actions.OpenMP().EndOpenMPClause();
2824 break;
2825 }
2826 // Skip ',' if any.
2827 if (Tok.is(tok::comma))
2828 ConsumeToken();
2829 Actions.OpenMP().EndOpenMPClause();
2830 }
2831 skipUntilPragmaOpenMPEnd(DKind);
2832 }
2833 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
2834 Loc, Helper.getIdentifiers(), Clauses);
2835 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2836 }
2837 SkipUntil(tok::annot_pragma_openmp_end);
2838 break;
2839 }
2840 case OMPD_declare_reduction:
2841 ConsumeToken();
2842 if (DeclGroupPtrTy Res =
2843 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2844 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2846 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2847 } else {
2848 SkipUntil(tok::annot_pragma_openmp_end);
2849 }
2850 break;
2851 case OMPD_declare_mapper: {
2852 ConsumeToken();
2853 if (DeclGroupPtrTy Res =
2854 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2855 // Skip the last annot_pragma_openmp_end.
2856 ConsumeAnnotationToken();
2857 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2858 } else {
2859 SkipUntil(tok::annot_pragma_openmp_end);
2860 }
2861 break;
2862 }
2863 case OMPD_declare_target: {
2864 SourceLocation DTLoc = ConsumeAnyToken();
2865 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2866 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2867 if (HasClauses)
2868 ParseOMPDeclareTargetClauses(DTCI);
2869 bool HasImplicitMappings =
2870 !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2871
2872 if (HasImplicitMappings) {
2873 Diag(Tok, diag::err_omp_unexpected_directive)
2874 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2875 SkipUntil(tok::annot_pragma_openmp_end);
2876 break;
2877 }
2878
2879 // Skip the last annot_pragma_openmp_end.
2881
2882 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2883 break;
2884 }
2885 case OMPD_begin_declare_variant: {
2886 ConsumeToken();
2888 // Skip the last annot_pragma_openmp_end.
2889 if (!isEofOrEom())
2890 ConsumeAnnotationToken();
2891 }
2892 return Directive;
2893 }
2894 case OMPD_end_declare_variant: {
2895 ConsumeToken();
2896 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2897 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2898 else
2899 Diag(Loc, diag::err_expected_begin_declare_variant);
2900 ConsumeAnnotationToken();
2901 break;
2902 }
2903 case OMPD_declare_simd:
2904 case OMPD_begin_declare_target:
2905 case OMPD_end_declare_target:
2906 case OMPD_requires:
2907 case OMPD_declare_variant:
2908 Diag(Tok, diag::err_omp_unexpected_directive)
2909 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2910 SkipUntil(tok::annot_pragma_openmp_end);
2911 break;
2912 case OMPD_assume: {
2913 ConsumeToken();
2914 Directive = ParseOpenMPInformationalDirective(
2915 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2916 assert(!Directive.isUnset() &&
2917 "Informational directive remains unprocessed");
2918 return Directive;
2919 }
2920 case OMPD_unknown:
2921 default:
2922 Diag(Tok, diag::err_omp_unknown_directive);
2923 SkipUntil(tok::annot_pragma_openmp_end);
2924 break;
2925 }
2926 return Directive;
2927}
2928
2929bool Parser::ParseOpenMPSimpleVarList(
2931 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2932 &Callback,
2933 bool AllowScopeSpecifier) {
2934 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2935 // Parse '('.
2936 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2937 if (T.expectAndConsume(diag::err_expected_lparen_after,
2938 getOpenMPDirectiveName(Kind, OMPVersion).data()))
2939 return true;
2940 bool IsCorrect = true;
2941 bool NoIdentIsFound = true;
2942
2943 // Read tokens while ')' or annot_pragma_openmp_end is not found.
2944 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2945 CXXScopeSpec SS;
2946 UnqualifiedId Name;
2947 // Read var name.
2948 Token PrevTok = Tok;
2949 NoIdentIsFound = false;
2950
2951 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2952 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2953 /*ObjectHasErrors=*/false, false)) {
2954 IsCorrect = false;
2955 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2957 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2958 /*ObjectHadErrors=*/false, false, false,
2959 false, false, nullptr, Name)) {
2960 IsCorrect = false;
2961 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2963 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2964 Tok.isNot(tok::annot_pragma_openmp_end)) {
2965 IsCorrect = false;
2966 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2968 Diag(PrevTok.getLocation(), diag::err_expected)
2969 << tok::identifier
2970 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2971 } else {
2972 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2973 }
2974 // Consume ','.
2975 if (Tok.is(tok::comma)) {
2976 ConsumeToken();
2977 }
2978 }
2979
2980 if (NoIdentIsFound) {
2981 Diag(Tok, diag::err_expected) << tok::identifier;
2982 IsCorrect = false;
2983 }
2984
2985 // Parse ')'.
2986 IsCorrect = !T.consumeClose() && IsCorrect;
2987
2988 return !IsCorrect;
2989}
2990
2991OMPClause *Parser::ParseOpenMPSizesClause() {
2992 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
2993 SmallVector<Expr *, 4> ValExprs;
2994 if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
2995 ValExprs))
2996 return nullptr;
2997
2998 return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
2999 OpenLoc, CloseLoc);
3000}
3001
3002OMPClause *Parser::ParseOpenMPCountsClause() {
3003 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3004 SmallVector<Expr *, 4> ValExprs;
3005 std::optional<unsigned> FillIdx;
3006 unsigned FillCount = 0;
3007 SourceLocation FillLoc;
3008
3009 assert(getOpenMPClauseName(OMPC_counts) == PP.getSpelling(Tok) &&
3010 "Expected parsing to start at clause name");
3011 ClauseNameLoc = ConsumeToken();
3012
3013 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3014 if (T.consumeOpen()) {
3015 Diag(Tok, diag::err_expected) << tok::l_paren;
3016 return nullptr;
3017 }
3018
3019 do {
3020 if (Tok.is(tok::identifier) &&
3021 Tok.getIdentifierInfo()->getName() == "omp_fill") {
3022 if (FillCount == 0)
3023 FillIdx = ValExprs.size();
3024 ++FillCount;
3025 FillLoc = Tok.getLocation();
3026 ConsumeToken();
3027 ValExprs.push_back(nullptr);
3028 } else {
3030 if (!Val.isUsable()) {
3031 T.skipToEnd();
3032 return nullptr;
3033 }
3034 ValExprs.push_back(Val.get());
3035 }
3036 } while (TryConsumeToken(tok::comma));
3037
3038 if (T.consumeClose())
3039 return nullptr;
3040 OpenLoc = T.getOpenLocation();
3041 CloseLoc = T.getCloseLocation();
3042
3043 return Actions.OpenMP().ActOnOpenMPCountsClause(
3044 ValExprs, ClauseNameLoc, OpenLoc, CloseLoc, FillIdx, FillLoc, FillCount);
3045}
3046
3047OMPClause *Parser::ParseOpenMPLoopRangeClause() {
3048 SourceLocation ClauseNameLoc = ConsumeToken();
3049 SourceLocation FirstLoc, CountLoc;
3050
3051 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3052 if (T.consumeOpen()) {
3053 Diag(Tok, diag::err_expected) << tok::l_paren;
3054 return nullptr;
3055 }
3056
3057 FirstLoc = Tok.getLocation();
3059 if (!FirstVal.isUsable()) {
3060 T.skipToEnd();
3061 return nullptr;
3062 }
3063
3064 ExpectAndConsume(tok::comma);
3065
3066 CountLoc = Tok.getLocation();
3068 if (!CountVal.isUsable()) {
3069 T.skipToEnd();
3070 return nullptr;
3071 }
3072
3073 T.consumeClose();
3074
3075 return Actions.OpenMP().ActOnOpenMPLoopRangeClause(
3076 FirstVal.get(), CountVal.get(), ClauseNameLoc, T.getOpenLocation(),
3077 FirstLoc, CountLoc, T.getCloseLocation());
3078}
3079
3080OMPClause *Parser::ParseOpenMPPermutationClause() {
3081 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3082 SmallVector<Expr *> ArgExprs;
3083 if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,
3084 CloseLoc, ArgExprs,
3085 /*ReqIntConst=*/true))
3086 return nullptr;
3087
3088 return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,
3089 OpenLoc, CloseLoc);
3090}
3091
3092OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3093 SourceLocation Loc = Tok.getLocation();
3095
3096 // Parse '('.
3097 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3098 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
3099 return nullptr;
3100 SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
3101 do {
3102 // Parse 'traits(expr) : Allocator' for >=5.2
3103 if (getLangOpts().OpenMP >= 52 && Tok.is(tok::identifier) &&
3104 Tok.getIdentifierInfo()->getName() == "traits") {
3105
3106 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3107
3108 ConsumeToken();
3109
3110 // Parse '(' <expr> ')'
3111 BalancedDelimiterTracker TraitParens(*this, tok::l_paren,
3112 tok::annot_pragma_openmp_end);
3113 TraitParens.consumeOpen();
3114 ExprResult AllocatorTraits =
3115 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3116 TraitParens.consumeClose();
3117
3118 if (AllocatorTraits.isInvalid()) {
3119 SkipUntil(
3120 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3122 break;
3123 }
3124
3125 // Expect ':'
3126 if (Tok.isNot(tok::colon)) {
3127 Diag(Tok, diag::err_expected) << tok::colon;
3128 SkipUntil(
3129 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3131 continue;
3132 }
3133 ConsumeToken();
3134
3135 CXXScopeSpec SS;
3136 ExprResult AllocatorExpr =
3137 getLangOpts().CPlusPlus
3138 ? ParseCXXIdExpression()
3139 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false);
3140
3141 if (AllocatorExpr.isInvalid()) {
3142 SkipUntil(
3143 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3145 break;
3146 }
3147
3148 D.Allocator = AllocatorExpr.get();
3149 D.AllocatorTraits = AllocatorTraits.get();
3150 D.LParenLoc = TraitParens.getOpenLocation();
3151 D.RParenLoc = TraitParens.getCloseLocation();
3152
3153 // Separator handling(;)
3154 if (Tok.is(tok::comma)) {
3155 // In 5.2, comma is invalid
3156 Diag(Tok.getLocation(), diag::err_omp_allocator_comma_separator)
3157 << FixItHint::CreateReplacement(Tok.getLocation(), ";");
3159 } else if (Tok.is(tok::semi)) {
3160 ConsumeAnyToken(); // valid separator
3161 }
3162
3163 continue;
3164 }
3165
3166 // Parse 'Allocator(expr)' for <5.2
3167 CXXScopeSpec SS;
3168 ExprResult Allocator =
3169 getLangOpts().CPlusPlus
3170 ? ParseCXXIdExpression()
3171 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false);
3172 if (Allocator.isInvalid()) {
3173 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3174 StopBeforeMatch);
3175 break;
3176 }
3177 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3178 D.Allocator = Allocator.get();
3179 if (Tok.is(tok::l_paren)) {
3180 BalancedDelimiterTracker T(*this, tok::l_paren,
3181 tok::annot_pragma_openmp_end);
3182 T.consumeOpen();
3183 ExprResult AllocatorTraits =
3184 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3185 T.consumeClose();
3186 if (AllocatorTraits.isInvalid()) {
3187 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3188 StopBeforeMatch);
3189 break;
3190 }
3191 D.AllocatorTraits = AllocatorTraits.get();
3192 D.LParenLoc = T.getOpenLocation();
3193 D.RParenLoc = T.getCloseLocation();
3194
3195 // Deprecation diagnostic in >= 5.2
3196 if (getLangOpts().OpenMP >= 52) {
3197 Diag(Loc, diag::err_omp_deprecate_old_syntax)
3198 << "allocator(expr)" // %0: old form
3199 << "uses_allocators" // %1: clause name
3200 << "traits(expr): alloc"; // %2: suggested new form
3201 }
3202 }
3203 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3204 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
3205 // Parse ','
3206 if (Tok.is(tok::comma))
3207 ConsumeAnyToken();
3208 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
3209 T.consumeClose();
3210 return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3211 Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
3212}
3213
3214OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3215 OpenMPClauseKind CKind, bool FirstClause) {
3216 OMPClauseKind = CKind;
3217 OMPClause *Clause = nullptr;
3218 bool ErrorFound = false;
3219 bool WrongDirective = false;
3220 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
3221
3222 // Check if clause is allowed for the given directive.
3223 if (CKind != OMPC_unknown &&
3224 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
3225 Diag(Tok, diag::err_omp_unexpected_clause)
3226 << getOpenMPClauseName(CKind)
3227 << getOpenMPDirectiveName(DKind, OMPVersion);
3228 ErrorFound = true;
3229 WrongDirective = true;
3230 }
3231
3232 switch (CKind) {
3233 case OMPC_final:
3234 case OMPC_num_threads:
3235 case OMPC_safelen:
3236 case OMPC_simdlen:
3237 case OMPC_collapse:
3238 case OMPC_ordered:
3239 case OMPC_priority:
3240 case OMPC_grainsize:
3241 case OMPC_num_tasks:
3242 case OMPC_hint:
3243 case OMPC_allocator:
3244 case OMPC_depobj:
3245 case OMPC_detach:
3246 case OMPC_novariants:
3247 case OMPC_nocontext:
3248 case OMPC_filter:
3249 case OMPC_partial:
3250 case OMPC_align:
3251 case OMPC_message:
3252 case OMPC_ompx_dyn_cgroup_mem:
3253 case OMPC_dyn_groupprivate:
3254 case OMPC_transparent:
3255 // OpenMP [2.5, Restrictions]
3256 // At most one num_threads clause can appear on the directive.
3257 // OpenMP [2.8.1, simd construct, Restrictions]
3258 // Only one safelen clause can appear on a simd directive.
3259 // Only one simdlen clause can appear on a simd directive.
3260 // Only one collapse clause can appear on a simd directive.
3261 // OpenMP [2.11.1, task Construct, Restrictions]
3262 // At most one if clause can appear on the directive.
3263 // At most one final clause can appear on the directive.
3264 // OpenMP [teams Construct, Restrictions]
3265 // At most one num_teams clause can appear on the directive.
3266 // At most one thread_limit clause can appear on the directive.
3267 // OpenMP [2.9.1, task Construct, Restrictions]
3268 // At most one priority clause can appear on the directive.
3269 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3270 // At most one grainsize clause can appear on the directive.
3271 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3272 // At most one num_tasks clause can appear on the directive.
3273 // OpenMP [2.11.3, allocate Directive, Restrictions]
3274 // At most one allocator clause can appear on the directive.
3275 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3276 // At most one detach clause can appear on the directive.
3277 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3278 // At most one novariants clause can appear on a dispatch directive.
3279 // At most one nocontext clause can appear on a dispatch directive.
3280 // OpenMP [5.1, error directive, Restrictions]
3281 // At most one message clause can appear on the directive
3282 if (!FirstClause) {
3283 Diag(Tok, diag::err_omp_more_one_clause)
3284 << getOpenMPDirectiveName(DKind, OMPVersion)
3285 << getOpenMPClauseName(CKind) << 0;
3286 ErrorFound = true;
3287 }
3288
3289 if (CKind == OMPC_transparent && PP.LookAhead(0).isNot(tok::l_paren)) {
3290 SourceLocation Loc = ConsumeToken();
3291 SourceLocation LLoc = Tok.getLocation();
3292 Clause = Actions.OpenMP().ActOnOpenMPTransparentClause(nullptr, LLoc,
3293 LLoc, Loc);
3294 break;
3295 }
3296 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3297 PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3298 Clause = ParseOpenMPClause(CKind, WrongDirective);
3299 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
3300 CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)
3301 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3302 else
3303 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3304 break;
3305 case OMPC_threadset:
3306 case OMPC_fail:
3307 case OMPC_proc_bind:
3308 case OMPC_atomic_default_mem_order:
3309 case OMPC_at:
3310 case OMPC_severity:
3311 case OMPC_bind:
3312 // OpenMP [2.14.3.1, Restrictions]
3313 // Only a single default clause may be specified on a parallel, task or
3314 // teams directive.
3315 // OpenMP [2.5, parallel Construct, Restrictions]
3316 // At most one proc_bind clause can appear on the directive.
3317 // OpenMP [5.0, Requires directive, Restrictions]
3318 // At most one atomic_default_mem_order clause can appear
3319 // on the directive
3320 // OpenMP [5.1, error directive, Restrictions]
3321 // At most one at clause can appear on the directive
3322 // At most one severity clause can appear on the directive
3323 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3324 // At most one bind clause can appear on a loop directive.
3325 if (!FirstClause) {
3326 Diag(Tok, diag::err_omp_more_one_clause)
3327 << getOpenMPDirectiveName(DKind, OMPVersion)
3328 << getOpenMPClauseName(CKind) << 0;
3329 ErrorFound = true;
3330 }
3331
3332 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3333 break;
3334 case OMPC_device:
3335 case OMPC_schedule:
3336 case OMPC_dist_schedule:
3337 case OMPC_defaultmap:
3338 case OMPC_default:
3339 case OMPC_order:
3340 // OpenMP [2.7.1, Restrictions, p. 3]
3341 // Only one schedule clause can appear on a loop directive.
3342 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3343 // At most one defaultmap clause can appear on the directive.
3344 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3345 // At most one device clause can appear on the directive.
3346 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3347 // At most one order clause may appear on a construct.
3348 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3349 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3350 Diag(Tok, diag::err_omp_more_one_clause)
3351 << getOpenMPDirectiveName(DKind, OMPVersion)
3352 << getOpenMPClauseName(CKind) << 0;
3353 ErrorFound = true;
3354 }
3355 [[fallthrough]];
3356 case OMPC_if:
3357 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3358 break;
3359 case OMPC_holds:
3360 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3361 break;
3362 case OMPC_nowait:
3363 case OMPC_untied:
3364 case OMPC_mergeable:
3365 case OMPC_read:
3366 case OMPC_write:
3367 case OMPC_capture:
3368 case OMPC_compare:
3369 case OMPC_seq_cst:
3370 case OMPC_acq_rel:
3371 case OMPC_acquire:
3372 case OMPC_release:
3373 case OMPC_relaxed:
3374 case OMPC_weak:
3375 case OMPC_threads:
3376 case OMPC_simd:
3377 case OMPC_nogroup:
3378 case OMPC_unified_address:
3379 case OMPC_unified_shared_memory:
3380 case OMPC_reverse_offload:
3381 case OMPC_dynamic_allocators:
3382 case OMPC_full:
3383 // OpenMP [2.7.1, Restrictions, p. 9]
3384 // Only one ordered clause can appear on a loop directive.
3385 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3386 // Only one nowait clause can appear on a for directive.
3387 // OpenMP [5.0, Requires directive, Restrictions]
3388 // Each of the requires clauses can appear at most once on the directive.
3389 if (!FirstClause) {
3390 Diag(Tok, diag::err_omp_more_one_clause)
3391 << getOpenMPDirectiveName(DKind, OMPVersion)
3392 << getOpenMPClauseName(CKind) << 0;
3393 ErrorFound = true;
3394 }
3395
3396 if (CKind == OMPC_nowait && PP.LookAhead(/*N=*/0).is(tok::l_paren) &&
3397 getLangOpts().OpenMP >= 60)
3398 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3399 else
3400 Clause = ParseOpenMPClause(CKind, WrongDirective);
3401 break;
3402 case OMPC_self_maps:
3403 // OpenMP [6.0, self_maps clause]
3404 if (getLangOpts().OpenMP < 60) {
3405 Diag(Tok, diag::err_omp_expected_clause)
3406 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
3407 ErrorFound = true;
3408 }
3409 if (!FirstClause) {
3410 Diag(Tok, diag::err_omp_more_one_clause)
3411 << getOpenMPDirectiveName(DKind, OMPVersion)
3412 << getOpenMPClauseName(CKind) << 0;
3413 ErrorFound = true;
3414 }
3415 Clause = ParseOpenMPClause(CKind, WrongDirective);
3416 break;
3417 case OMPC_update:
3418 if (!FirstClause) {
3419 Diag(Tok, diag::err_omp_more_one_clause)
3420 << getOpenMPDirectiveName(DKind, OMPVersion)
3421 << getOpenMPClauseName(CKind) << 0;
3422 ErrorFound = true;
3423 }
3424
3425 Clause = (DKind == OMPD_depobj)
3426 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3427 : ParseOpenMPClause(CKind, WrongDirective);
3428 break;
3429 case OMPC_num_teams:
3430 case OMPC_thread_limit:
3431 if (!FirstClause) {
3432 Diag(Tok, diag::err_omp_more_one_clause)
3433 << getOpenMPDirectiveName(DKind, OMPVersion)
3434 << getOpenMPClauseName(CKind) << 0;
3435 ErrorFound = true;
3436 }
3437 [[fallthrough]];
3438 case OMPC_private:
3439 case OMPC_firstprivate:
3440 case OMPC_lastprivate:
3441 case OMPC_shared:
3442 case OMPC_reduction:
3443 case OMPC_task_reduction:
3444 case OMPC_in_reduction:
3445 case OMPC_linear:
3446 case OMPC_aligned:
3447 case OMPC_copyin:
3448 case OMPC_copyprivate:
3449 case OMPC_flush:
3450 case OMPC_depend:
3451 case OMPC_map:
3452 case OMPC_to:
3453 case OMPC_from:
3454 case OMPC_use_device_ptr:
3455 case OMPC_use_device_addr:
3456 case OMPC_is_device_ptr:
3457 case OMPC_has_device_addr:
3458 case OMPC_allocate:
3459 case OMPC_nontemporal:
3460 case OMPC_inclusive:
3461 case OMPC_exclusive:
3462 case OMPC_affinity:
3463 case OMPC_doacross:
3464 case OMPC_enter:
3465 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3466 CKind == OMPC_depend)
3467 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3468 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3469 break;
3470 case OMPC_sizes:
3471 if (!FirstClause) {
3472 Diag(Tok, diag::err_omp_more_one_clause)
3473 << getOpenMPDirectiveName(DKind, OMPVersion)
3474 << getOpenMPClauseName(CKind) << 0;
3475 ErrorFound = true;
3476 }
3477
3478 Clause = ParseOpenMPSizesClause();
3479 break;
3480 case OMPC_permutation:
3481 if (!FirstClause) {
3482 Diag(Tok, diag::err_omp_more_one_clause)
3483 << getOpenMPDirectiveName(DKind, OMPVersion)
3484 << getOpenMPClauseName(CKind) << 0;
3485 ErrorFound = true;
3486 }
3487 Clause = ParseOpenMPPermutationClause();
3488 break;
3489 case OMPC_counts:
3490 if (!FirstClause) {
3491 Diag(Tok, diag::err_omp_more_one_clause)
3492 << getOpenMPDirectiveName(DKind, OMPVersion)
3493 << getOpenMPClauseName(CKind) << 0;
3494 ErrorFound = true;
3495 }
3496 Clause = ParseOpenMPCountsClause();
3497 break;
3498 case OMPC_uses_allocators:
3499 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3500 break;
3501 case OMPC_destroy:
3502 if (DKind != OMPD_interop) {
3503 if (!FirstClause) {
3504 Diag(Tok, diag::err_omp_more_one_clause)
3505 << getOpenMPDirectiveName(DKind, OMPVersion)
3506 << getOpenMPClauseName(CKind) << 0;
3507 ErrorFound = true;
3508 }
3509 Clause = ParseOpenMPClause(CKind, WrongDirective);
3510 break;
3511 }
3512 [[fallthrough]];
3513 case OMPC_init:
3514 case OMPC_use:
3515 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3516 break;
3517 case OMPC_device_type:
3518 case OMPC_unknown:
3519 skipUntilPragmaOpenMPEnd(DKind);
3520 break;
3521 case OMPC_threadprivate:
3522 case OMPC_groupprivate:
3523 case OMPC_uniform:
3524 case OMPC_match:
3525 if (!WrongDirective)
3526 Diag(Tok, diag::err_omp_unexpected_clause)
3527 << getOpenMPClauseName(CKind)
3528 << getOpenMPDirectiveName(DKind, OMPVersion);
3529 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3530 break;
3531 case OMPC_absent:
3532 case OMPC_contains: {
3533 SourceLocation Loc = ConsumeToken();
3534 SourceLocation LLoc = Tok.getLocation();
3535 SourceLocation RLoc;
3536 llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
3537 BalancedDelimiterTracker T(*this, tok::l_paren);
3538 T.consumeOpen();
3539 do {
3540 OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
3541 if (DK == OMPD_unknown) {
3542 skipUntilPragmaOpenMPEnd(OMPD_assume);
3543 Diag(Tok, diag::err_omp_unexpected_clause)
3544 << getOpenMPClauseName(CKind)
3545 << getOpenMPDirectiveName(DKind, OMPVersion);
3546 break;
3547 }
3549 DKVec.push_back(DK);
3550 ConsumeToken();
3551 } else {
3552 Diag(Tok, diag::err_omp_unexpected_clause)
3553 << getOpenMPClauseName(CKind)
3554 << getOpenMPDirectiveName(DKind, OMPVersion);
3555 }
3556 } while (TryConsumeToken(tok::comma));
3557 RLoc = Tok.getLocation();
3558 T.consumeClose();
3559 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3560 CKind, DKVec, Loc, LLoc, RLoc);
3561 break;
3562 }
3563 case OMPC_no_openmp:
3564 case OMPC_no_openmp_routines:
3565 case OMPC_no_openmp_constructs:
3566 case OMPC_no_parallelism: {
3567 if (!FirstClause) {
3568 Diag(Tok, diag::err_omp_more_one_clause)
3569 << getOpenMPDirectiveName(DKind, OMPVersion)
3570 << getOpenMPClauseName(CKind) << 0;
3571 ErrorFound = true;
3572 }
3573 SourceLocation Loc = ConsumeToken();
3574 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3575 CKind, Loc, Tok.getLocation());
3576 break;
3577 }
3578 case OMPC_ompx_attribute:
3579 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3580 break;
3581 case OMPC_ompx_bare:
3582 if (DKind == llvm::omp::Directive::OMPD_target) {
3583 // Flang splits the combined directives which requires OMPD_target to be
3584 // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
3585 // to explicitly check whether this clause is applied to an `omp target`
3586 // without `teams` and emit an error.
3587 Diag(Tok, diag::err_omp_unexpected_clause)
3588 << getOpenMPClauseName(CKind)
3589 << getOpenMPDirectiveName(DKind, OMPVersion);
3590 ErrorFound = true;
3591 WrongDirective = true;
3592 }
3593 if (WrongDirective)
3594 Diag(Tok, diag::note_ompx_bare_clause)
3595 << getOpenMPClauseName(CKind) << "target teams";
3596 if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3597 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3598 << getOpenMPClauseName(CKind)
3599 << getOpenMPDirectiveName(DKind, OMPVersion);
3600 ErrorFound = true;
3601 }
3602 Clause = ParseOpenMPClause(CKind, WrongDirective);
3603 break;
3604 case OMPC_looprange:
3605 Clause = ParseOpenMPLoopRangeClause();
3606 break;
3607 default:
3608 break;
3609 }
3610 return ErrorFound ? nullptr : Clause;
3611}
3612
3613/// Parses simple expression in parens for single-expression clauses of OpenMP
3614/// constructs.
3615/// \param RLoc Returned location of right paren.
3617 SourceLocation &RLoc,
3618 bool IsAddressOfOperand) {
3619 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3620 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3621 return ExprError();
3622
3623 SourceLocation ELoc = Tok.getLocation();
3624 ExprResult LHS(
3625 ParseCastExpression(CastParseKind::AnyCastExpr, IsAddressOfOperand,
3627 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3628 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3629
3630 // Parse ')'.
3631 RLoc = Tok.getLocation();
3632 if (!T.consumeClose())
3633 RLoc = T.getCloseLocation();
3634
3635 return Val;
3636}
3637
3638OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3639 bool ParseOnly) {
3641 SourceLocation LLoc = Tok.getLocation();
3642 SourceLocation RLoc;
3643
3644 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3645
3646 if (Val.isInvalid())
3647 return nullptr;
3648
3649 if (ParseOnly)
3650 return nullptr;
3651 return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3652 LLoc, RLoc);
3653}
3654
3655bool Parser::ParseOpenMPIndirectClause(
3656 SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3658 SourceLocation RLoc;
3659
3660 if (Tok.isNot(tok::l_paren)) {
3661 if (ParseOnly)
3662 return false;
3663 DTCI.Indirect = nullptr;
3664 return true;
3665 }
3666
3667 ExprResult Val =
3668 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3669 if (Val.isInvalid())
3670 return false;
3671
3672 if (ParseOnly)
3673 return false;
3674
3675 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3676 !Val.get()->isInstantiationDependent() &&
3678 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3679 if (Ret.isInvalid())
3680 return false;
3681 llvm::APSInt Result;
3682 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3684 if (Ret.isInvalid())
3685 return false;
3686 DTCI.Indirect = Val.get();
3687 return true;
3688 }
3689 return false;
3690}
3691
3692ExprResult Parser::ParseOMPInteropFrSelector() {
3693 ConsumeToken(); // 'fr'
3694 BalancedDelimiterTracker FT(*this, tok::l_paren,
3695 tok::annot_pragma_openmp_end);
3696 if (FT.expectAndConsume(diag::err_expected_lparen_after, "fr")) {
3697 SkipUntil(
3698 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3700 return ExprError();
3701 }
3702 SourceLocation Loc = Tok.getLocation();
3703 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3704 ExprResult Arg = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3705 Arg = Actions.ActOnFinishFullExpr(Arg.get(), Loc, /*DiscardedValue=*/false);
3706 FT.consumeClose();
3707 return Arg;
3708}
3709
3710bool Parser::ParseOMPInteropAttrSelector(SmallVectorImpl<Expr *> &Attrs) {
3711 ConsumeToken(); // 'attr'
3712 BalancedDelimiterTracker AT(*this, tok::l_paren,
3713 tok::annot_pragma_openmp_end);
3714 if (AT.expectAndConsume(diag::err_expected_lparen_after, "attr")) {
3715 SkipUntil(
3716 {tok::comma, tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end},
3718 return true;
3719 }
3720 bool HasError = false;
3721 // attr() requires at least one ext-string-literal argument; an empty list is
3722 // not permitted by the prefer_type grammar.
3723 if (Tok.is(tok::r_paren)) {
3724 Diag(Tok, diag::err_omp_interop_attr_not_string);
3725 HasError = true;
3726 }
3727 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::r_brace) &&
3728 Tok.isNot(tok::annot_pragma_openmp_end)) {
3729 if (Tok.is(tok::string_literal)) {
3731 if (S.isUsable())
3732 Attrs.push_back(S.get());
3733 else
3734 HasError = true;
3735 } else {
3736 HasError = true;
3737 Diag(Tok, diag::err_omp_interop_attr_not_string);
3738 ConsumeToken();
3739 }
3740 if (Tok.is(tok::comma))
3741 ConsumeToken();
3742 }
3743 AT.consumeClose();
3744 return HasError;
3745}
3746
3747bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3748 OpenMPClauseKind Kind) {
3749 const Token &Tok = getCurToken();
3750 bool HasError = false;
3751 bool IsTarget = false;
3752 bool IsTargetSync = false;
3753
3754 while (Tok.is(tok::identifier)) {
3755 // Currently prefer_type is only allowed with 'init' and it must be first.
3756 bool PreferTypeAllowed = Kind == OMPC_init && InteropInfo.Prefs.empty() &&
3757 !IsTarget && !IsTargetSync;
3758 if (Tok.getIdentifierInfo()->isStr("target")) {
3759 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3760 // Each interop-type may be specified on an action-clause at most
3761 // once.
3762 if (IsTarget)
3763 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3764 IsTarget = true;
3765 ConsumeToken();
3766 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3767 if (IsTargetSync)
3768 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3769 IsTargetSync = true;
3770 ConsumeToken();
3771 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3772 PreferTypeAllowed) {
3773 ConsumeToken();
3774 BalancedDelimiterTracker PT(*this, tok::l_paren,
3775 tok::annot_pragma_openmp_end);
3776 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3777 HasError = true;
3778
3779 // prefer_type requires at least one preference-specification.
3780 if (Tok.is(tok::r_paren)) {
3781 Diag(Tok, diag::err_omp_expected_pref_spec);
3782 HasError = true;
3783 }
3784
3785 while (Tok.isNot(tok::r_paren) &&
3786 Tok.isNot(tok::annot_pragma_openmp_end)) {
3787 // OMP 6.0: { fr(...), attr(...) } brace-grouped pref-spec
3788 if (Tok.is(tok::l_brace)) {
3789 // The brace-grouped form was introduced in OpenMP 6.0; earlier
3790 // versions only allow the flat foreign-runtime-id list.
3791 if (getLangOpts().OpenMP < 60) {
3792 Diag(Tok, diag::err_omp_prefer_type_brace_60);
3793 HasError = true;
3794 }
3795 BalancedDelimiterTracker BT(*this, tok::l_brace,
3796 tok::annot_pragma_openmp_end);
3797 BT.consumeOpen();
3798 Expr *FrExpr = nullptr;
3799 SmallVector<Expr *, 2> AttrExprs;
3800 bool SeenFr = false;
3801
3802 // A pref-spec requires at least one 'fr'/'attr' selector; {} is not
3803 // permitted by the grammar.
3804 if (Tok.is(tok::r_brace)) {
3805 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3806 HasError = true;
3807 }
3808
3809 while (Tok.isNot(tok::r_brace) &&
3810 Tok.isNot(tok::annot_pragma_openmp_end)) {
3811 if (Tok.is(tok::identifier) &&
3812 Tok.getIdentifierInfo()->isStr("fr")) {
3813 if (SeenFr) {
3814 Diag(Tok, diag::err_omp_interop_multiple_fr);
3815 HasError = true;
3816 ConsumeToken(); // 'fr'
3817 SkipUntil(
3818 {tok::comma, tok::r_brace, tok::annot_pragma_openmp_end},
3820 continue;
3821 }
3822 SeenFr = true;
3823 ExprResult Fr = ParseOMPInteropFrSelector();
3824 if (Fr.isUsable())
3825 FrExpr = Fr.get();
3826 else
3827 HasError = true;
3828 } else if (Tok.is(tok::identifier) &&
3829 Tok.getIdentifierInfo()->isStr("attr")) {
3830 if (ParseOMPInteropAttrSelector(AttrExprs))
3831 HasError = true;
3832 } else {
3833 // Neither 'fr' nor 'attr' (a non-identifier or some other word).
3834 HasError = true;
3835 Diag(Tok, diag::err_omp_expected_fr_or_attr_selector);
3836 ConsumeToken();
3837 }
3838 if (Tok.is(tok::comma))
3839 ConsumeToken();
3840 }
3841 if (BT.consumeClose())
3842 HasError = true;
3843
3844 if (FrExpr || !AttrExprs.empty())
3845 InteropInfo.Prefs.emplace_back(FrExpr, AttrExprs);
3846 InteropInfo.HasPreferAttrs = true;
3847 } else {
3848 // OMP 5.1: flat foreign-runtime-id (string or int). Stored as a
3849 // pref-spec with Fr=expr and no attr() entries.
3850 SourceLocation Loc = Tok.getLocation();
3851 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3852 ExprResult PTExpr =
3853 ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3854 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3855 /*DiscardedValue=*/false);
3856 if (PTExpr.isUsable()) {
3857 InteropInfo.Prefs.emplace_back(PTExpr.get(),
3858 llvm::SmallVector<Expr *, 2>{});
3859 } else {
3860 HasError = true;
3861 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3863 }
3864 }
3865
3866 if (Tok.is(tok::comma))
3867 ConsumeToken();
3868 }
3869 PT.consumeClose();
3870 } else {
3871 HasError = true;
3872 Diag(Tok, diag::err_omp_expected_interop_type);
3873 ConsumeToken();
3874 }
3875 if (!Tok.is(tok::comma))
3876 break;
3877 ConsumeToken();
3878 }
3879
3880 if (!HasError && !IsTarget && !IsTargetSync) {
3881 Diag(Tok, diag::err_omp_expected_interop_type);
3882 HasError = true;
3883 }
3884
3885 if (Kind == OMPC_init) {
3886 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3887 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3888 if (Tok.is(tok::colon))
3889 ConsumeToken();
3890 }
3891
3892 // As of OpenMP 5.1,there are two interop-types, "target" and
3893 // "targetsync". Either or both are allowed for a single interop.
3894 InteropInfo.IsTarget = IsTarget;
3895 InteropInfo.IsTargetSync = IsTargetSync;
3896
3897 return HasError;
3898}
3899
3900OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3901 bool ParseOnly) {
3902 SourceLocation Loc = ConsumeToken();
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 bool InteropError = false;
3910 OMPInteropInfo InteropInfo;
3911 if (Kind == OMPC_init)
3912 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3913
3914 // Parse the variable.
3915 SourceLocation VarLoc = Tok.getLocation();
3916 ExprResult InteropVarExpr = ParseAssignmentExpression();
3917 if (!InteropVarExpr.isUsable()) {
3918 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3920 }
3921
3922 // Parse ')'.
3923 SourceLocation RLoc = Tok.getLocation();
3924 if (!T.consumeClose())
3925 RLoc = T.getCloseLocation();
3926
3927 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3928 return nullptr;
3929
3930 if (Kind == OMPC_init)
3931 return Actions.OpenMP().ActOnOpenMPInitClause(
3932 InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3933 RLoc);
3934 if (Kind == OMPC_use)
3935 return Actions.OpenMP().ActOnOpenMPUseClause(
3936 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3937
3938 if (Kind == OMPC_destroy)
3939 return Actions.OpenMP().ActOnOpenMPDestroyClause(
3940 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3941
3942 llvm_unreachable("Unexpected interop variable clause.");
3943}
3944
3945OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3946 SourceLocation Loc = ConsumeToken();
3947 // Parse '('.
3948 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3949 if (T.expectAndConsume(diag::err_expected_lparen_after,
3950 getOpenMPClauseName(OMPC_ompx_attribute).data()))
3951 return nullptr;
3952
3953 ParsedAttributes ParsedAttrs(AttrFactory);
3954 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
3955
3956 // Parse ')'.
3957 if (T.consumeClose())
3958 return nullptr;
3959
3960 if (ParseOnly)
3961 return nullptr;
3962
3963 SmallVector<Attr *> Attrs;
3964 for (const ParsedAttr &PA : ParsedAttrs) {
3965 switch (PA.getKind()) {
3966 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3967 if (!PA.checkExactlyNumArgs(Actions, 2))
3968 continue;
3969 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
3970 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
3971 Attrs.push_back(A);
3972 continue;
3973 case ParsedAttr::AT_AMDGPUWavesPerEU:
3974 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3975 !PA.checkAtMostNumArgs(Actions, 2))
3976 continue;
3977 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
3978 PA, PA.getArgAsExpr(0),
3979 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
3980 Attrs.push_back(A);
3981 continue;
3982 case ParsedAttr::AT_CUDALaunchBounds:
3983 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3984 !PA.checkAtMostNumArgs(Actions, 3))
3985 continue;
3986 if (auto *A = Actions.CreateLaunchBoundsAttr(
3987 PA, PA.getArgAsExpr(0),
3988 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
3989 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr,
3990 /*IgnoreArch=*/true))
3991 Attrs.push_back(A);
3992 continue;
3993 default:
3994 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3995 continue;
3996 };
3997 }
3998
3999 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
4000 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
4001}
4002
4003OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
4004 bool ParseOnly) {
4005 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
4006 if (!Val || ParseOnly)
4007 return nullptr;
4008 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
4009 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
4010 static_cast<DefaultKind>(Val->Type) ==
4011 OMP_DEFAULT_firstprivate)) {
4012 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
4013 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
4014 OMP_DEFAULT_private
4015 ? OMPC_private
4016 : OMPC_firstprivate)
4017 << getOpenMPClauseName(OMPC_default) << "5.1";
4018 return nullptr;
4019 }
4020 return Actions.OpenMP().ActOnOpenMPSimpleClause(
4021 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
4022}
4023
4024OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
4025 SourceLocation Loc = Tok.getLocation();
4027
4028 if (ParseOnly)
4029 return nullptr;
4030 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
4031}
4032
4033OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
4034 OpenMPClauseKind Kind,
4035 bool ParseOnly) {
4036 SourceLocation Loc = ConsumeToken();
4037 SourceLocation DelimLoc;
4038 // Parse '('.
4039 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4040 if (T.expectAndConsume(diag::err_expected_lparen_after,
4041 getOpenMPClauseName(Kind).data()))
4042 return nullptr;
4043
4044 ExprResult Val;
4045 SmallVector<unsigned, 4> Arg;
4046 SmallVector<SourceLocation, 4> KLoc;
4047 if (Kind == OMPC_schedule) {
4048 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
4049 Arg.resize(NumberOfElements);
4050 KLoc.resize(NumberOfElements);
4051 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
4052 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
4053 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
4054 unsigned KindModifier = getOpenMPSimpleClauseType(
4055 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4056 if (KindModifier > OMPC_SCHEDULE_unknown) {
4057 // Parse 'modifier'
4058 Arg[Modifier1] = KindModifier;
4059 KLoc[Modifier1] = Tok.getLocation();
4060 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4061 Tok.isNot(tok::annot_pragma_openmp_end))
4063 if (Tok.is(tok::comma)) {
4064 // Parse ',' 'modifier'
4066 KindModifier = getOpenMPSimpleClauseType(
4067 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4068 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
4069 ? KindModifier
4070 : (unsigned)OMPC_SCHEDULE_unknown;
4071 KLoc[Modifier2] = Tok.getLocation();
4072 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4073 Tok.isNot(tok::annot_pragma_openmp_end))
4075 }
4076 // Parse ':'
4077 if (Tok.is(tok::colon))
4079 else
4080 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
4081 KindModifier = getOpenMPSimpleClauseType(
4082 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4083 }
4084 Arg[ScheduleKind] = KindModifier;
4085 KLoc[ScheduleKind] = Tok.getLocation();
4086 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4087 Tok.isNot(tok::annot_pragma_openmp_end))
4089 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
4090 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
4091 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
4092 Tok.is(tok::comma))
4093 DelimLoc = ConsumeAnyToken();
4094 } else if (Kind == OMPC_dist_schedule) {
4095 Arg.push_back(getOpenMPSimpleClauseType(
4096 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4097 KLoc.push_back(Tok.getLocation());
4098 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4099 Tok.isNot(tok::annot_pragma_openmp_end))
4101 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
4102 DelimLoc = ConsumeAnyToken();
4103 } else if (Kind == OMPC_default) {
4104 // Get a default modifier
4105 unsigned Modifier = getOpenMPSimpleClauseType(
4106 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4107
4108 Arg.push_back(Modifier);
4109 KLoc.push_back(Tok.getLocation());
4110 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4111 Tok.isNot(tok::annot_pragma_openmp_end))
4113 // Parse ':'
4114 if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {
4116 // Get a variable-category attribute for default clause modifier
4117 OpenMPDefaultClauseVariableCategory VariableCategory =
4119 Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4120 Arg.push_back(VariableCategory);
4121 KLoc.push_back(Tok.getLocation());
4122 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4123 Tok.isNot(tok::annot_pragma_openmp_end))
4125 } else {
4126 Arg.push_back(OMPC_DEFAULT_VC_all);
4127 KLoc.push_back(SourceLocation());
4128 }
4129 } else if (Kind == OMPC_defaultmap) {
4130 // Get a defaultmap modifier
4131 unsigned Modifier = getOpenMPSimpleClauseType(
4132 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4133
4134 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
4135 // pointer
4136 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
4138 Arg.push_back(Modifier);
4139 KLoc.push_back(Tok.getLocation());
4140 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4141 Tok.isNot(tok::annot_pragma_openmp_end))
4143 // Parse ':'
4144 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
4145 if (Tok.is(tok::colon))
4147 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
4148 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
4149 // Get a defaultmap kind
4150 Arg.push_back(getOpenMPSimpleClauseType(
4151 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4152 KLoc.push_back(Tok.getLocation());
4153 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4154 Tok.isNot(tok::annot_pragma_openmp_end))
4156 } else {
4157 Arg.push_back(OMPC_DEFAULTMAP_unknown);
4158 KLoc.push_back(SourceLocation());
4159 }
4160 } else if (Kind == OMPC_order) {
4161 enum { Modifier, OrderKind, NumberOfElements };
4162 Arg.resize(NumberOfElements);
4163 KLoc.resize(NumberOfElements);
4164 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
4165 Arg[OrderKind] = OMPC_ORDER_unknown;
4166 unsigned KindModifier = getOpenMPSimpleClauseType(
4167 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4168 if (KindModifier > OMPC_ORDER_unknown) {
4169 // Parse 'modifier'
4170 Arg[Modifier] = KindModifier;
4171 KLoc[Modifier] = Tok.getLocation();
4172 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4173 Tok.isNot(tok::annot_pragma_openmp_end))
4175 // Parse ':'
4176 if (Tok.is(tok::colon))
4178 else
4179 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
4180 KindModifier = getOpenMPSimpleClauseType(
4181 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4182 }
4183 Arg[OrderKind] = KindModifier;
4184 KLoc[OrderKind] = Tok.getLocation();
4185 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4186 Tok.isNot(tok::annot_pragma_openmp_end))
4188 } else if (Kind == OMPC_device) {
4189 // Only target executable directives support extended device construct.
4190 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4191 NextToken().is(tok::colon)) {
4192 // Parse optional <device modifier> ':'
4193 Arg.push_back(getOpenMPSimpleClauseType(
4194 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4195 KLoc.push_back(Tok.getLocation());
4197 // Parse ':'
4199 } else {
4200 Arg.push_back(OMPC_DEVICE_unknown);
4201 KLoc.emplace_back();
4202 }
4203 } else if (Kind == OMPC_grainsize) {
4204 // Parse optional <grainsize modifier> ':'
4207 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4208 getLangOpts()));
4209 if (getLangOpts().OpenMP >= 51) {
4210 if (NextToken().is(tok::colon)) {
4211 Arg.push_back(Modifier);
4212 KLoc.push_back(Tok.getLocation());
4213 // Parse modifier
4215 // Parse ':'
4217 } else {
4218 if (Modifier == OMPC_GRAINSIZE_strict) {
4219 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4220 // Parse modifier
4222 }
4223 Arg.push_back(OMPC_GRAINSIZE_unknown);
4224 KLoc.emplace_back();
4225 }
4226 } else {
4227 Arg.push_back(OMPC_GRAINSIZE_unknown);
4228 KLoc.emplace_back();
4229 }
4230 } else if (Kind == OMPC_dyn_groupprivate) {
4231 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
4232 Arg.resize(NumberOfModifiers);
4233 KLoc.resize(NumberOfModifiers);
4234 Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
4235 Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
4236
4237 auto ConsumeModifier = [&]() {
4238 unsigned Type = NumberOfModifiers;
4239 unsigned Modifier;
4240 SourceLocation Loc;
4241 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
4242 NextToken().is(tok::l_paren)) {
4243 ConsumeToken();
4244 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4245 ParenT.consumeOpen();
4246
4247 Modifier = getOpenMPSimpleClauseType(
4248 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4251 Diag(Tok.getLocation(), diag::err_expected)
4252 << "'abort', 'null' or 'default_mem' in fallback modifier";
4253 SkipUntil(tok::r_paren);
4254 return std::make_tuple(Type, Modifier, Loc);
4255 }
4256 Type = ComplexModifier;
4257 Loc = Tok.getLocation();
4258 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4259 Tok.isNot(tok::annot_pragma_openmp_end))
4261 ParenT.consumeClose();
4262 } else {
4263 Modifier = getOpenMPSimpleClauseType(
4264 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4265 if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
4266 Type = SimpleModifier;
4267 Loc = Tok.getLocation();
4268 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4269 Tok.isNot(tok::annot_pragma_openmp_end))
4271 }
4272 }
4273 return std::make_tuple(Type, Modifier, Loc);
4274 };
4275
4276 auto SaveModifier = [&](unsigned Type, unsigned Modifier,
4277 SourceLocation Loc) {
4278 assert(Type < NumberOfModifiers && "Unexpected modifier type");
4279 if (!KLoc[Type].isValid()) {
4280 Arg[Type] = Modifier;
4281 KLoc[Type] = Loc;
4282 } else {
4283 Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
4284 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
4285 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
4286 }
4287 };
4288
4289 // Parse 'modifier'
4290 auto [Type1, Mod1, Loc1] = ConsumeModifier();
4291 if (Type1 < NumberOfModifiers) {
4292 SaveModifier(Type1, Mod1, Loc1);
4293 if (Tok.is(tok::comma)) {
4294 // Parse ',' 'modifier'
4296 auto [Type2, Mod2, Loc2] = ConsumeModifier();
4297 if (Type2 < NumberOfModifiers)
4298 SaveModifier(Type2, Mod2, Loc2);
4299 }
4300 // Parse ':'
4301 if (Tok.is(tok::colon))
4303 else
4304 Diag(Tok, diag::warn_pragma_expected_colon)
4305 << "dyn_groupprivate modifier";
4306 }
4307 } else if (Kind == OMPC_num_tasks) {
4308 // Parse optional <num_tasks modifier> ':'
4311 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4312 getLangOpts()));
4313 if (getLangOpts().OpenMP >= 51) {
4314 if (NextToken().is(tok::colon)) {
4315 Arg.push_back(Modifier);
4316 KLoc.push_back(Tok.getLocation());
4317 // Parse modifier
4319 // Parse ':'
4321 } else {
4322 if (Modifier == OMPC_NUMTASKS_strict) {
4323 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4324 // Parse modifier
4326 }
4327 Arg.push_back(OMPC_NUMTASKS_unknown);
4328 KLoc.emplace_back();
4329 }
4330 } else {
4331 Arg.push_back(OMPC_NUMTASKS_unknown);
4332 KLoc.emplace_back();
4333 }
4334 } else if (Kind == OMPC_num_threads) {
4335 // Parse optional <num_threads modifier> ':'
4338 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4339 getLangOpts()));
4340 if (getLangOpts().OpenMP >= 60) {
4341 if (NextToken().is(tok::colon)) {
4342 Arg.push_back(Modifier);
4343 KLoc.push_back(Tok.getLocation());
4344 // Parse modifier
4346 // Parse ':'
4348 } else {
4349 if (Modifier == OMPC_NUMTHREADS_strict) {
4350 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4351 // Parse modifier
4353 }
4354 Arg.push_back(OMPC_NUMTHREADS_unknown);
4355 KLoc.emplace_back();
4356 }
4357 } else {
4358 Arg.push_back(OMPC_NUMTHREADS_unknown);
4359 KLoc.emplace_back();
4360 }
4361 } else {
4362 assert(Kind == OMPC_if);
4363 KLoc.push_back(Tok.getLocation());
4364 TentativeParsingAction TPA(*this);
4365 auto DK = parseOpenMPDirectiveKind(*this);
4366 Arg.push_back(static_cast<unsigned>(DK));
4367 if (DK != OMPD_unknown) {
4368 ConsumeToken();
4369 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4370 TPA.Commit();
4371 DelimLoc = ConsumeToken();
4372 } else {
4373 TPA.Revert();
4374 Arg.back() = unsigned(OMPD_unknown);
4375 }
4376 } else {
4377 TPA.Revert();
4378 }
4379 }
4380
4381 bool NeedAnExpression =
4382 (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4383 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||
4384 Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
4385 Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;
4386 if (NeedAnExpression) {
4387 SourceLocation ELoc = Tok.getLocation();
4388 ExprResult LHS(
4389 ParseCastExpression(CastParseKind::AnyCastExpr, false,
4391 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4392 Val =
4393 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4394 }
4395
4396 // Parse ')'.
4397 SourceLocation RLoc = Tok.getLocation();
4398 if (!T.consumeClose())
4399 RLoc = T.getCloseLocation();
4400
4401 if (NeedAnExpression && Val.isInvalid())
4402 return nullptr;
4403
4404 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
4405 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
4406 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
4407 Diag(KLoc[0], diag::err_omp_invalid_dsa)
4408 << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==
4409 OMP_DEFAULT_private
4410 ? OMPC_private
4411 : OMPC_firstprivate)
4412 << getOpenMPClauseName(OMPC_default) << "5.1";
4413 return nullptr;
4414 }
4415
4416 if (ParseOnly)
4417 return nullptr;
4418 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4419 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4420}
4421
4422static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4423 UnqualifiedId &ReductionId) {
4424 if (ReductionIdScopeSpec.isEmpty()) {
4425 auto OOK = OO_None;
4426 switch (P.getCurToken().getKind()) {
4427 case tok::plus:
4428 OOK = OO_Plus;
4429 break;
4430 case tok::minus:
4431 OOK = OO_Minus;
4432 break;
4433 case tok::star:
4434 OOK = OO_Star;
4435 break;
4436 case tok::amp:
4437 OOK = OO_Amp;
4438 break;
4439 case tok::pipe:
4440 OOK = OO_Pipe;
4441 break;
4442 case tok::caret:
4443 OOK = OO_Caret;
4444 break;
4445 case tok::ampamp:
4446 OOK = OO_AmpAmp;
4447 break;
4448 case tok::pipepipe:
4449 OOK = OO_PipePipe;
4450 break;
4451 default:
4452 break;
4453 }
4454 if (OOK != OO_None) {
4455 SourceLocation OpLoc = P.ConsumeToken();
4456 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4457 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4458 return false;
4459 }
4460 }
4461 return P.ParseUnqualifiedId(
4462 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4463 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4464 /*AllowDestructorName*/ false,
4465 /*AllowConstructorName*/ false,
4466 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4467}
4468
4469/// Checks if the token is a valid map-type-modifier.
4470/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4472 Token Tok = P.getCurToken();
4473 if (!Tok.is(tok::identifier))
4475
4476 Preprocessor &PP = P.getPreprocessor();
4477 OpenMPMapModifierKind TypeModifier =
4479 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4480 return TypeModifier;
4481}
4482
4484 // Parse '('.
4485 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4486 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4487 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4489 return true;
4490 }
4491 // Parse mapper-identifier
4492 if (getLangOpts().CPlusPlus)
4493 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4494 /*ObjectType=*/nullptr,
4495 /*ObjectHasErrors=*/false,
4496 /*EnteringContext=*/false);
4497 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4498 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4499 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4501 return true;
4502 }
4503 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4504 Data.ReductionOrMapperId = DeclarationNameInfo(
4505 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4506 ConsumeToken();
4507 // Parse ')'.
4508 return T.consumeClose();
4509}
4510
4512
4514 bool HasMapType = false;
4515 SourceLocation PreMapLoc = Tok.getLocation();
4516 StringRef PreMapName = "";
4517 while (getCurToken().isNot(tok::colon)) {
4518 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4519 OpenMPMapClauseKind MapKind = isMapType(*this);
4520 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4521 TypeModifier == OMPC_MAP_MODIFIER_close ||
4522 TypeModifier == OMPC_MAP_MODIFIER_present ||
4523 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4524 Data.MapTypeModifiers.push_back(TypeModifier);
4525 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4526 if (PP.LookAhead(0).isNot(tok::comma) &&
4527 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4528 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4529 << "map type modifier";
4530 ConsumeToken();
4531 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4532 Data.MapTypeModifiers.push_back(TypeModifier);
4533 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4534 ConsumeToken();
4536 return true;
4537 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4538 getLangOpts().OpenMP >= 52)
4539 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4540 << "map type modifier";
4541
4542 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4543 if (!HasMapType) {
4544 HasMapType = true;
4545 Data.ExtraModifier = MapKind;
4546 MapKind = OMPC_MAP_unknown;
4547 PreMapLoc = Tok.getLocation();
4548 PreMapName = Tok.getIdentifierInfo()->getName();
4549 } else {
4550 Diag(Tok, diag::err_omp_more_one_map_type);
4551 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4552 << PreMapName;
4553 }
4554 ConsumeToken();
4555 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
4556 Data.MapTypeModifiers.push_back(TypeModifier);
4557 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4558 if (PP.LookAhead(0).isNot(tok::comma) &&
4559 PP.LookAhead(0).isNot(tok::colon))
4560 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4561 << "map type modifier";
4562 if (getLangOpts().OpenMP < 60)
4563 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4564 << (getLangOpts().OpenMP >= 51
4565 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4566 : 0)
4567 << getLangOpts().OpenMPExtensions << 0;
4568 ConsumeToken();
4569 } else {
4570 // For the case of unknown map-type-modifier or a map-type.
4571 // Map-type is followed by a colon; the function returns when it
4572 // encounters a token followed by a colon.
4573 if (Tok.is(tok::comma)) {
4574 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4575 ConsumeToken();
4576 continue;
4577 }
4578 // Potential map-type token as it is followed by a colon.
4579 if (PP.LookAhead(0).is(tok::colon)) {
4580 if (getLangOpts().OpenMP >= 60) {
4581 break;
4582 } else {
4583 return false;
4584 }
4585 }
4586
4587 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4588 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4589 : 0)
4590 << getLangOpts().OpenMPExtensions
4591 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
4592 ConsumeToken();
4593 }
4594 if (getCurToken().is(tok::comma))
4595 ConsumeToken();
4596 }
4597 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4598 if (!Tok.is(tok::colon)) {
4599 Diag(Tok, diag::err_omp_unknown_map_type);
4600 ConsumeToken();
4601 } else {
4602 Data.ExtraModifier = OMPC_MAP_unknown;
4603 }
4604 }
4605 return false;
4606}
4607
4608/// Checks if the token is a valid map-type.
4609/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4611 Token Tok = P.getCurToken();
4612 // The map-type token can be either an identifier or the C++ delete keyword.
4613 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4614 return OMPC_MAP_unknown;
4615 Preprocessor &PP = P.getPreprocessor();
4616 unsigned MapType =
4618 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4619 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4620 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4621 return static_cast<OpenMPMapClauseKind>(MapType);
4622 return OMPC_MAP_unknown;
4623}
4624
4625/// Parse map-type in map clause.
4626/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4627/// where, map-type ::= to | from | tofrom | alloc | release | delete
4629 Token Tok = P.getCurToken();
4630 if (Tok.is(tok::colon)) {
4631 P.Diag(Tok, diag::err_omp_map_type_missing);
4632 return;
4633 }
4634 Data.ExtraModifier = isMapType(P);
4635 if (Data.ExtraModifier == OMPC_MAP_unknown)
4636 P.Diag(Tok, diag::err_omp_unknown_map_type);
4637 P.ConsumeToken();
4638}
4639
4640ExprResult Parser::ParseOpenMPIteratorsExpr() {
4641 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4642 "Expected 'iterator' token.");
4643 SourceLocation IteratorKwLoc = ConsumeToken();
4644
4645 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4646 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4647 return ExprError();
4648
4649 SourceLocation LLoc = T.getOpenLocation();
4650 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4651 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4652 // Check if the type parsing is required.
4653 ParsedType IteratorType;
4654 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4655 // identifier '=' is not found - parse type.
4657 if (TR.isInvalid()) {
4658 T.skipToEnd();
4659 return ExprError();
4660 }
4661 IteratorType = TR.get();
4662 }
4663
4664 // Parse identifier.
4665 IdentifierInfo *II = nullptr;
4666 SourceLocation IdLoc;
4667 if (Tok.is(tok::identifier)) {
4668 II = Tok.getIdentifierInfo();
4669 IdLoc = ConsumeToken();
4670 } else {
4671 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4672 }
4673
4674 // Parse '='.
4675 SourceLocation AssignLoc;
4676 if (Tok.is(tok::equal))
4677 AssignLoc = ConsumeToken();
4678 else
4679 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4680
4681 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4682 ColonProtectionRAIIObject ColonRAII(*this);
4683 // Parse <begin>
4684 SourceLocation Loc = Tok.getLocation();
4685 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4686 ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4687 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4688 /*DiscardedValue=*/false);
4689 // Parse ':'.
4690 SourceLocation ColonLoc;
4691 if (Tok.is(tok::colon))
4692 ColonLoc = ConsumeToken();
4693
4694 // Parse <end>
4695 Loc = Tok.getLocation();
4696 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4697 ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4698 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4699 /*DiscardedValue=*/false);
4700
4701 SourceLocation SecColonLoc;
4702 ExprResult Step;
4703 // Parse optional step.
4704 if (Tok.is(tok::colon)) {
4705 // Parse ':'
4706 SecColonLoc = ConsumeToken();
4707 // Parse <step>
4708 Loc = Tok.getLocation();
4709 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4710 Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4711 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4712 /*DiscardedValue=*/false);
4713 }
4714
4715 // Parse ',' or ')'
4716 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4717 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4718 if (Tok.is(tok::comma))
4719 ConsumeToken();
4720
4721 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4722 D.DeclIdent = II;
4723 D.DeclIdentLoc = IdLoc;
4724 D.Type = IteratorType;
4725 D.AssignLoc = AssignLoc;
4726 D.ColonLoc = ColonLoc;
4727 D.SecColonLoc = SecColonLoc;
4728 D.Range.Begin = Begin.get();
4729 D.Range.End = End.get();
4730 D.Range.Step = Step.get();
4731 }
4732
4733 // Parse ')'.
4734 SourceLocation RLoc = Tok.getLocation();
4735 if (!T.consumeClose())
4736 RLoc = T.getCloseLocation();
4737
4738 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4739 LLoc, RLoc, Data);
4740}
4741
4744 const LangOptions &LangOpts) {
4745 // Currently the only reserved locator is 'omp_all_memory' which is only
4746 // allowed on a depend clause.
4747 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4748 return false;
4749
4750 if (Tok.is(tok::identifier) &&
4751 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4752
4753 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4754 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4755 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4756 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4757 Data.ExtraModifier != OMPC_DEPEND_inout)
4758 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4759 else
4760 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4761 ? OMPC_DEPEND_outallmemory
4762 : OMPC_DEPEND_inoutallmemory;
4763 ConsumeToken();
4764 return true;
4765 }
4766 return false;
4767}
4768
4769/// Parse step size expression. Returns true if parsing is successfull,
4770/// otherwise returns false.
4772 OpenMPClauseKind CKind, SourceLocation ELoc) {
4774 Sema &Actions = P.getActions();
4775 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4776 /*DiscardedValue*/ false);
4777 if (Tail.isUsable()) {
4778 Data.DepModOrTailExpr = Tail.get();
4779 Token CurTok = P.getCurToken();
4780 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4781 P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4782 }
4783 return true;
4784 }
4785 return false;
4786}
4787
4788/// Parse 'allocate' clause modifiers.
4789/// If allocator-modifier exists, return an expression for it. For both
4790/// allocator and align modifiers, set Data fields as appropriate.
4791static ExprResult
4794 const Token &Tok = P.getCurToken();
4795 Preprocessor &PP = P.getPreprocessor();
4796 ExprResult Tail;
4797 ExprResult Val;
4798 SourceLocation RLoc;
4799 bool AllocatorSeen = false;
4800 bool AlignSeen = false;
4801 SourceLocation CurrentModifierLoc = Tok.getLocation();
4802 auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4804
4805 // Modifiers did not exist before 5.1
4806 if (P.getLangOpts().OpenMP < 51)
4807 return P.ParseAssignmentExpression();
4808
4809 // An allocator-simple-modifier is exclusive and must appear alone. See
4810 // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
4811 // description of "exclusive" property. If we don't recognized an explicit
4812 // simple-/complex- modifier, assume we're looking at expression
4813 // representing allocator and consider ourselves done.
4814 if (CurrentModifier == OMPC_ALLOCATE_unknown)
4815 return P.ParseAssignmentExpression();
4816
4817 do {
4818 P.ConsumeToken();
4819 if (Tok.is(tok::l_paren)) {
4820 switch (CurrentModifier) {
4821 case OMPC_ALLOCATE_allocator: {
4822 if (AllocatorSeen) {
4823 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4824 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4825 << getOpenMPClauseName(Kind);
4826 } else {
4827 Data.AllocClauseModifiers.push_back(CurrentModifier);
4828 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4829 }
4830 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
4831 tok::annot_pragma_openmp_end);
4832 AllocateT.consumeOpen();
4833 Tail = P.ParseAssignmentExpression();
4834 AllocateT.consumeClose();
4835 AllocatorSeen = true;
4836 break;
4837 }
4838 case OMPC_ALLOCATE_align: {
4839 if (AlignSeen) {
4840 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4841 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4842 << getOpenMPClauseName(Kind);
4843 } else {
4844 Data.AllocClauseModifiers.push_back(CurrentModifier);
4845 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4846 }
4847 Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
4848 if (Val.isUsable())
4849 Data.AllocateAlignment = Val.get();
4850 AlignSeen = true;
4851 break;
4852 }
4853 default:
4854 llvm_unreachable("Unexpected allocate modifier");
4855 }
4856 } else {
4857 P.Diag(Tok, diag::err_expected) << tok::l_paren;
4858 }
4859 if (Tok.isNot(tok::comma))
4860 break;
4861 P.ConsumeToken();
4862 CurrentModifierLoc = Tok.getLocation();
4863 CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4865 // A modifier followed by a comma implies another modifier.
4866 if (CurrentModifier == OMPC_ALLOCATE_unknown) {
4867 P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
4868 break;
4869 }
4870 } while (!AllocatorSeen || !AlignSeen);
4871 return Tail;
4872}
4873
4875 OpenMPClauseKind Kind,
4878 UnqualifiedId UnqualifiedReductionId;
4879 bool InvalidReductionId = false;
4880 bool IsInvalidMapperModifier = false;
4881
4882 // Parse '('.
4883 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4884 if (T.expectAndConsume(diag::err_expected_lparen_after,
4885 getOpenMPClauseName(Kind).data()))
4886 return true;
4887
4888 bool HasIterator = false;
4889 bool InvalidIterator = false;
4890 bool NeedRParenForLinear = false;
4891 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4892 tok::annot_pragma_openmp_end);
4893 // Handle reduction-identifier for reduction clause.
4894 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4895 Kind == OMPC_in_reduction) {
4896 Data.ExtraModifier = OMPC_REDUCTION_unknown;
4897 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4898 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4899 NextToken().is(tok::comma)) {
4900 // Parse optional reduction modifier.
4901 Data.ExtraModifier =
4902 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4903 Data.ExtraModifierLoc = Tok.getLocation();
4904 ConsumeToken();
4905 assert(Tok.is(tok::comma) && "Expected comma.");
4906 (void)ConsumeToken();
4907 }
4908 // Handle original(private / shared) Modifier
4909 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
4910 Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
4911 NextToken().is(tok::l_paren)) {
4912 // Parse original(private) modifier.
4913 ConsumeToken();
4914 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4915 ParenT.consumeOpen();
4916 if (Tok.is(tok::kw_private)) {
4917 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
4918 Data.OriginalSharingModifierLoc = Tok.getLocation();
4919 ConsumeToken();
4920 } else if (Tok.is(tok::identifier) &&
4921 (PP.getSpelling(Tok) == "shared" ||
4922 PP.getSpelling(Tok) == "default")) {
4923 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
4924 Data.OriginalSharingModifierLoc = Tok.getLocation();
4925 ConsumeToken();
4926 } else {
4927 Diag(Tok.getLocation(), diag::err_expected)
4928 << "'private or shared or default'";
4929 SkipUntil(tok::r_paren);
4930 return false;
4931 }
4932 ParenT.consumeClose();
4933 if (!Tok.is(tok::comma)) {
4934 Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
4935 return false;
4936 }
4937 (void)ConsumeToken();
4938 }
4939 ColonProtectionRAIIObject ColonRAII(*this);
4940 if (getLangOpts().CPlusPlus)
4941 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4942 /*ObjectType=*/nullptr,
4943 /*ObjectHasErrors=*/false,
4944 /*EnteringContext=*/false);
4945 InvalidReductionId = ParseReductionId(
4946 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4947 if (InvalidReductionId) {
4948 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4950 }
4951 if (Tok.is(tok::colon))
4952 Data.ColonLoc = ConsumeToken();
4953 else
4954 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4955 if (!InvalidReductionId)
4956 Data.ReductionOrMapperId =
4957 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4958 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4959 if (getLangOpts().OpenMP >= 50) {
4960 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4961 // Handle optional dependence modifier.
4962 // iterator(iterators-definition)
4963 // where iterators-definition is iterator-specifier [,
4964 // iterators-definition ]
4965 // where iterator-specifier is [ iterator-type ] identifier =
4966 // range-specification
4967 HasIterator = true;
4969 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4970 Data.DepModOrTailExpr = IteratorRes.get();
4971 // Parse ','
4972 ExpectAndConsume(tok::comma);
4973 }
4974 }
4975 // Handle dependency type for depend clause.
4976 ColonProtectionRAIIObject ColonRAII(*this);
4977 Data.ExtraModifier = getOpenMPSimpleClauseType(
4978 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4979 getLangOpts());
4980 Data.ExtraModifierLoc = Tok.getLocation();
4981 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
4982 (Kind == OMPC_doacross &&
4983 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
4984 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4986 } else {
4987 ConsumeToken();
4988 // Special processing for depend(source) clause.
4989 if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4990 Data.ExtraModifier == OMPC_DEPEND_source) {
4991 // Parse ')'.
4992 T.consumeClose();
4993 return false;
4994 }
4995 }
4996 if (Tok.is(tok::colon)) {
4997 Data.ColonLoc = ConsumeToken();
4998 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
4999 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
5000 : diag::warn_pragma_expected_colon)
5001 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
5002 }
5003 if (Kind == OMPC_doacross) {
5004 if (Tok.is(tok::identifier) &&
5005 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
5006 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
5007 ? OMPC_DOACROSS_source_omp_cur_iteration
5008 : OMPC_DOACROSS_sink_omp_cur_iteration;
5009 ConsumeToken();
5010 }
5011 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
5012 if (Tok.isNot(tok::minus)) {
5013 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5014 << getOpenMPClauseName(Kind) << 0 << 0;
5015 SkipUntil(tok::r_paren);
5016 return false;
5017 } else {
5018 ConsumeToken();
5019 SourceLocation Loc = Tok.getLocation();
5020 uint64_t Value = 0;
5021 if (Tok.isNot(tok::numeric_constant) ||
5022 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
5023 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
5024 << getOpenMPClauseName(Kind) << 0 << 0;
5025 SkipUntil(tok::r_paren);
5026 return false;
5027 }
5028 }
5029 }
5030 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
5031 if (Tok.isNot(tok::r_paren)) {
5032 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
5033 << getOpenMPClauseName(Kind) << 1 << 1;
5034 SkipUntil(tok::r_paren);
5035 return false;
5036 }
5037 }
5038 // Only the 'sink' case has the expression list.
5039 if (Kind == OMPC_doacross &&
5040 (Data.ExtraModifier == OMPC_DOACROSS_source ||
5041 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
5042 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
5043 // Parse ')'.
5044 T.consumeClose();
5045 return false;
5046 }
5047 }
5048 } else if (Kind == OMPC_linear) {
5049 // Try to parse modifier if any.
5050 Data.ExtraModifier = OMPC_LINEAR_val;
5051 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
5052 Data.ExtraModifier =
5053 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5054 Data.ExtraModifierLoc = ConsumeToken();
5055 LinearT.consumeOpen();
5056 NeedRParenForLinear = true;
5057 if (getLangOpts().OpenMP >= 52)
5058 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
5059 << "linear-modifier(list)" << getOpenMPClauseName(Kind)
5060 << "linear(list: [linear-modifier,] step(step-size))";
5061 }
5062 } else if (Kind == OMPC_lastprivate) {
5063 // Try to parse modifier if any.
5064 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
5065 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
5066 // distribute and taskloop based directives.
5067 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
5068 !isOpenMPTaskLoopDirective(DKind)) &&
5069 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
5070 Data.ExtraModifier =
5071 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
5072 Data.ExtraModifierLoc = Tok.getLocation();
5073 ConsumeToken();
5074 assert(Tok.is(tok::colon) && "Expected colon.");
5075 Data.ColonLoc = ConsumeToken();
5076 }
5077 } else if (Kind == OMPC_map) {
5078 // Handle optional iterator map modifier.
5079 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
5080 HasIterator = true;
5082 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
5083 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
5084 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
5085 Data.IteratorExpr = IteratorRes.get();
5086 // Parse ','
5087 ExpectAndConsume(tok::comma);
5088 if (getLangOpts().OpenMP < 52) {
5089 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
5090 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
5091 << getLangOpts().OpenMPExtensions << 0;
5092 InvalidIterator = true;
5093 }
5094 }
5095 // Handle map type for map clause.
5096 ColonProtectionRAIIObject ColonRAII(*this);
5097
5098 // The first identifier may be a list item, a map-type or a
5099 // map-type-modifier. The map-type can also be delete which has the same
5100 // spelling of the C++ delete keyword.
5101 Data.ExtraModifier = OMPC_MAP_unknown;
5102 Data.ExtraModifierLoc = Tok.getLocation();
5103
5104 // Check for presence of a colon in the map clause.
5105 TentativeParsingAction TPA(*this);
5106 bool ColonPresent = false;
5107 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5108 StopBeforeMatch)) {
5109 if (Tok.is(tok::colon))
5110 ColonPresent = true;
5111 }
5112 TPA.Revert();
5113 // Only parse map-type-modifier[s] and map-type if a colon is present in
5114 // the map clause.
5115 if (ColonPresent) {
5116 if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
5117 Diag(Tok, diag::err_omp_map_modifier_specification_list);
5118 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
5119 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
5120 parseMapType(*this, Data);
5121 else
5122 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
5123 }
5124 if (Data.ExtraModifier == OMPC_MAP_unknown) {
5125 Data.ExtraModifier = OMPC_MAP_tofrom;
5126 if (getLangOpts().OpenMP >= 52) {
5127 if (DKind == OMPD_target_enter_data)
5128 Data.ExtraModifier = OMPC_MAP_to;
5129 else if (DKind == OMPD_target_exit_data)
5130 Data.ExtraModifier = OMPC_MAP_from;
5131 }
5132 Data.IsMapTypeImplicit = true;
5133 }
5134
5135 if (Tok.is(tok::colon))
5136 Data.ColonLoc = ConsumeToken();
5137 } else if (Kind == OMPC_to || Kind == OMPC_from) {
5138 while (Tok.is(tok::identifier)) {
5139 auto Modifier = static_cast<OpenMPMotionModifierKind>(
5140 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5141 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
5142 break;
5143 Data.MotionModifiers.push_back(Modifier);
5144 Data.MotionModifiersLoc.push_back(Tok.getLocation());
5145 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
5146 ExprResult Tail;
5147 Tail = ParseOpenMPIteratorsExpr();
5148 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5149 /*DiscardedValue=*/false);
5150 if (Tail.isUsable())
5151 Data.IteratorExpr = Tail.get();
5152 } else {
5153 ConsumeToken();
5154 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
5155 IsInvalidMapperModifier = parseMapperModifier(Data);
5156 if (IsInvalidMapperModifier)
5157 break;
5158 }
5159 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
5160 if (getLangOpts().OpenMP < 51)
5161 break;
5162 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
5163 // TODO: Is that intentional?
5164 if (Tok.is(tok::comma))
5165 ConsumeToken();
5166 }
5167 }
5168 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
5169 if (!IsInvalidMapperModifier) {
5170 if (getLangOpts().OpenMP < 51)
5171 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
5172 else
5173 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
5174 }
5175 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
5177 }
5178 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
5179 // that intentional?
5180 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
5181 Tok.is(tok::colon))
5182 Data.ColonLoc = ConsumeToken();
5183 } else if (Kind == OMPC_allocate ||
5184 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
5185 PP.getSpelling(Tok) == "iterator")) {
5186 // Handle optional allocator and align modifiers followed by colon
5187 // delimiter.
5188 ColonProtectionRAIIObject ColonRAII(*this);
5189 TentativeParsingAction TPA(*this);
5190 // OpenMP 5.0, 2.10.1, task Construct.
5191 // where aff-modifier is one of the following:
5192 // iterator(iterators-definition)
5193 ExprResult Tail;
5194 if (Kind == OMPC_allocate) {
5195 Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
5196 } else {
5197 HasIterator = true;
5199 Tail = ParseOpenMPIteratorsExpr();
5200 }
5201 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5202 /*DiscardedValue=*/false);
5203 if (Tail.isUsable() || Data.AllocateAlignment) {
5204 if (Tok.is(tok::colon)) {
5205 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
5206 Data.ColonLoc = ConsumeToken();
5207 TPA.Commit();
5208 } else {
5209 // Colon not found, parse only list of variables.
5210 TPA.Revert();
5211 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
5212 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5214 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
5215 }
5216 }
5217 } else {
5218 // Parsing was unsuccessfull, revert and skip to the end of clause or
5219 // directive.
5220 TPA.Revert();
5221 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5223 }
5224 } else if (Kind == OMPC_adjust_args) {
5225 // Handle adjust-op for adjust_args clause.
5226 ColonProtectionRAIIObject ColonRAII(*this);
5227 Data.ExtraModifier = getOpenMPSimpleClauseType(
5228 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5229 getLangOpts());
5230 Data.ExtraModifierLoc = Tok.getLocation();
5231 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
5232 Diag(Tok, diag::err_omp_unknown_adjust_args_op)
5233 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
5234 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5235 } else {
5236 ConsumeToken();
5237 if (Tok.is(tok::colon))
5238 Data.ColonLoc = Tok.getLocation();
5239 if (getLangOpts().OpenMP >= 61) {
5240 // Handle the optional fallback argument for the need_device_ptr
5241 // modifier.
5242 if (Tok.is(tok::l_paren)) {
5243 BalancedDelimiterTracker T(*this, tok::l_paren);
5244 T.consumeOpen();
5245 if (Tok.is(tok::identifier)) {
5246 std::string Modifier = PP.getSpelling(Tok);
5247 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
5248 Data.NeedDevicePtrModifier =
5249 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
5250 : OMPC_NEED_DEVICE_PTR_fb_preserve;
5251 } else {
5252 Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);
5253 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5255 return false;
5256 }
5257 ConsumeToken();
5258 if (Tok.is(tok::r_paren)) {
5259 Data.NeedDevicePtrModifierLoc = Tok.getLocation();
5261 } else {
5262 Diag(Tok, diag::err_expected) << tok::r_paren;
5263 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5265 return false;
5266 }
5267 } else {
5268 Data.NeedDevicePtrModifier = OMPC_NEED_DEVICE_PTR_unknown;
5269 }
5270 }
5271 }
5272 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
5273 "adjust-op");
5274 }
5275 } else if (Kind == OMPC_use_device_ptr) {
5276 // Handle optional fallback modifier for use_device_ptr clause.
5277 // use_device_ptr([fb_preserve | fb_nullify :] list)
5279 if (getLangOpts().OpenMP >= 61 && Tok.is(tok::identifier)) {
5280 auto FallbackModifier = static_cast<OpenMPUseDevicePtrFallbackModifier>(
5281 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5282 if (FallbackModifier != OMPC_USE_DEVICE_PTR_FALLBACK_unknown) {
5283 Data.ExtraModifier = FallbackModifier;
5284 Data.ExtraModifierLoc = Tok.getLocation();
5285 ConsumeToken();
5286 if (Tok.is(tok::colon))
5287 Data.ColonLoc = ConsumeToken();
5288 else
5289 Diag(Tok, diag::err_modifier_expected_colon) << "fallback";
5290 }
5291 }
5292 } // Handle num_teams clause with optional lower-bound:upper-bound syntax
5293 if (Kind == OMPC_num_teams && !Tok.is(tok::r_paren) &&
5294 !Tok.is(tok::annot_pragma_openmp_end)) {
5296 if (FirstExpr.isInvalid()) {
5297 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5298 Data.RLoc = Tok.getLocation();
5299 if (!T.consumeClose())
5300 Data.RLoc = T.getCloseLocation();
5301 return true;
5302 }
5303
5304 if (Tok.is(tok::colon)) {
5305 // Lower-bound:upper-bound syntax
5306 ConsumeToken();
5308 if (UpperBound.isInvalid()) {
5309 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5310 Data.RLoc = Tok.getLocation();
5311 if (!T.consumeClose())
5312 Data.RLoc = T.getCloseLocation();
5313 return true;
5314 }
5315 Vars.push_back(FirstExpr.get()); // lower-bound
5316 Vars.push_back(UpperBound.get()); // upper-bound
5317 Data.RLoc = Tok.getLocation();
5318 if (!T.consumeClose())
5319 Data.RLoc = T.getCloseLocation();
5320 return false; // Success
5321 }
5322 if (Tok.is(tok::comma)) {
5323 Vars.push_back(FirstExpr.get());
5324 while (Tok.is(tok::comma)) {
5325 ConsumeToken();
5327 if (NextExpr.isUsable()) {
5328 Vars.push_back(NextExpr.get());
5329 } else {
5330 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5332 break;
5333 }
5334 }
5335 Data.RLoc = Tok.getLocation();
5336 bool HadError = T.consumeClose();
5337 if (!HadError)
5338 Data.RLoc = T.getCloseLocation();
5339 return HadError;
5340 }
5341
5342 // Single value - parse closing paren
5343 Vars.push_back(FirstExpr.get());
5344 Data.RLoc = Tok.getLocation();
5345 if (!T.consumeClose())
5346 Data.RLoc = T.getCloseLocation();
5347 return false; // Success
5348 }
5349
5350 bool IsComma =
5351 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
5352 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
5353 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
5354 (Kind == OMPC_reduction && !InvalidReductionId) ||
5355 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
5356 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
5357 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
5358 (Kind == OMPC_adjust_args &&
5359 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
5360 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
5361 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
5362 Tok.isNot(tok::annot_pragma_openmp_end))) {
5363 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
5364 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
5366 // Parse variable
5368 if (VarExpr.isUsable()) {
5369 Vars.push_back(VarExpr.get());
5370 } else {
5371 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5373 }
5374 }
5375 // Skip ',' if any
5376 IsComma = Tok.is(tok::comma);
5377 if (IsComma)
5378 ConsumeToken();
5379 else if (Tok.isNot(tok::r_paren) &&
5380 Tok.isNot(tok::annot_pragma_openmp_end) &&
5381 (!MayHaveTail || Tok.isNot(tok::colon))) {
5382 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
5383 Diag(Tok, diag::err_omp_expected_punc)
5384 << ((Kind == OMPC_flush)
5385 ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
5386 : getOpenMPClauseName(Kind))
5387 << (Kind == OMPC_flush);
5388 }
5389 }
5390
5391 // Parse ')' for linear clause with modifier.
5392 if (NeedRParenForLinear)
5393 LinearT.consumeClose();
5394 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
5395 // or parse ':' alignment.
5396 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
5397 bool StepFound = false;
5398 bool ModifierFound = false;
5399 if (MustHaveTail) {
5400 Data.ColonLoc = Tok.getLocation();
5402
5403 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
5404 bool Malformed = false;
5405 while (Tok.isNot(tok::r_paren)) {
5406 if (Tok.is(tok::identifier)) {
5407 // identifier could be a linear kind (val, uval, ref) or step
5408 // modifier or step size
5409 OpenMPLinearClauseKind LinKind =
5411 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5412 getLangOpts()));
5413
5414 if (LinKind == OMPC_LINEAR_step) {
5415 if (StepFound)
5416 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
5417
5418 BalancedDelimiterTracker StepT(*this, tok::l_paren,
5419 tok::annot_pragma_openmp_end);
5420 SourceLocation StepModifierLoc = ConsumeToken();
5421 // parse '('
5422 if (StepT.consumeOpen())
5423 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
5424
5425 // parse step size expression
5426 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5427 if (StepFound)
5428 Data.StepModifierLoc = StepModifierLoc;
5429
5430 // parse ')'
5431 StepT.consumeClose();
5432 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
5433 if (ModifierFound)
5434 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
5435
5436 Data.ExtraModifier = LinKind;
5437 Data.ExtraModifierLoc = ConsumeToken();
5438 ModifierFound = true;
5439 } else {
5440 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5441 if (!StepFound) {
5442 Malformed = true;
5443 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5445 }
5446 }
5447 } else {
5448 // parse an integer expression as step size
5449 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5450 }
5451
5452 if (Tok.is(tok::comma))
5453 ConsumeToken();
5454 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
5455 break;
5456 }
5457 if (!Malformed && !StepFound && !ModifierFound)
5458 Diag(ELoc, diag::err_expected_expression);
5459 } else {
5460 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
5462 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
5463 /*DiscardedValue*/ false);
5464 if (Tail.isUsable())
5465 Data.DepModOrTailExpr = Tail.get();
5466 else
5467 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5469 }
5470 }
5471
5472 // Parse ')'.
5473 Data.RLoc = Tok.getLocation();
5474 if (!T.consumeClose())
5475 Data.RLoc = T.getCloseLocation();
5476 // Exit from scope when the iterator is used in depend clause.
5477 if (HasIterator)
5478 ExitScope();
5479 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5480 Vars.empty()) ||
5481 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5482 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5483}
5484
5485OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5486 OpenMPClauseKind Kind,
5487 bool ParseOnly) {
5488 SourceLocation Loc = Tok.getLocation();
5489 SourceLocation LOpen = ConsumeToken();
5492
5493 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5494 return nullptr;
5495
5496 if (ParseOnly)
5497 return nullptr;
5498 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5499 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5500}
5501
5502bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5503 SourceLocation &ClauseNameLoc,
5504 SourceLocation &OpenLoc,
5505 SourceLocation &CloseLoc,
5507 bool ReqIntConst) {
5508 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5509 "Expected parsing to start at clause name");
5510 ClauseNameLoc = ConsumeToken();
5511
5512 // Parse inside of '(' and ')'.
5513 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5514 if (T.consumeOpen()) {
5515 Diag(Tok, diag::err_expected) << tok::l_paren;
5516 return true;
5517 }
5518
5519 // Parse the list with interleaved commas.
5520 do {
5521 ExprResult Val =
5523 if (!Val.isUsable()) {
5524 // Encountered something other than an expression; abort to ')'.
5525 T.skipToEnd();
5526 return true;
5527 }
5528 Exprs.push_back(Val.get());
5529 } while (TryConsumeToken(tok::comma));
5530
5531 bool Result = T.consumeClose();
5532 OpenLoc = T.getOpenLocation();
5533 CloseLoc = T.getCloseLocation();
5534 return Result;
5535}
Defines the clang::ASTContext interface.
bool is(tok::TokenKind Kind) const
Token Tok
The Token.
bool isNot(T Kind) const
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
static OpenMPDirectiveKind checkOpenMPDirectiveName(Parser &P, SourceLocation Loc, OpenMPDirectiveKind Kind, StringRef Name)
static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P)
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)
static ExprResult parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse 'allocate' clause modifiers.
static DeclarationName parseOpenMPReductionId(Parser &P)
static ExprResult parseContextScore(Parser &P)
Parse optional 'score' '(' <expr> ')' ':'.
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)
Parse step size expression.
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, SmallVectorImpl< Expr * > &Uniforms, SmallVectorImpl< Expr * > &Aligneds, SmallVectorImpl< Expr * > &Alignments, SmallVectorImpl< Expr * > &Linears, SmallVectorImpl< unsigned > &LinModifiers, SmallVectorImpl< Expr * > &Steps)
Parses clauses for 'declare simd' directive.
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This file declares semantic analysis functions specific to AMDGPU.
This file declares facilities that support code completion.
This file declares semantic analysis for OpenMP constructs and clauses.
Defines the clang::TokenKind enum and support functions.
VerifyDiagnosticConsumer::Directive Directive
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
llvm::SmallVector< OMPTraitSet, 2 > Sets
The outermost level of selector sets.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
DeclarationNameTable DeclarationNames
Definition ASTContext.h:806
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:6380
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:4356
@ 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:8748
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:1805
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:3183
Represents a C++ unqualified-id that has been parsed.
Definition DeclSpec.h:1039
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
Defines the clang::TargetInfo interface.
PRESERVE_NONE bool Ret(InterpState &S, CodePtr &PC)
Definition Interp.h:260
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:1902
@ 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:1256
@ OMPC_DEVICE_unknown
Definition OpenMPKinds.h:51
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition Ownership.h:230
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition OpenMPKinds.h:79
@ OMPC_MAP_MODIFIER_unknown
Definition OpenMPKinds.h:80
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition OpenMPKinds.h:28
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ OMPC_ORDER_unknown
@ OMPC_SCHEDULE_unknown
Definition OpenMPKinds.h:35
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
OpenMPDefaultClauseVariableCategory getOpenMPDefaultVariableCategory(StringRef Str, const LangOptions &LangOpts)
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition OpenMPKinds.h:71
@ OMPC_MAP_unknown
Definition OpenMPKinds.h:75
int const char * function
Definition c++config.h:31
#define false
Definition stdbool.h:26
llvm::omp::TraitProperty Kind
StringRef RawString
The raw string as we parsed it. This is needed for the isa trait set (which accepts anything) and (la...
llvm::omp::TraitSelector Kind
SmallVector< OMPTraitProperty, 1 > Properties
SmallVector< OMPTraitSelector, 2 > Selectors
llvm::omp::TraitSet Kind
Clang specific specialization of the OMPContext to lookup target features.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
llvm::SmallVector< OMPInteropPref, 4 > Prefs
This structure contains most locations needed for by an OMPVarListClause.
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition SemaOpenMP.h: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.