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