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