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