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