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 RequiresToLinkLocalOrIndirectClause = false;
1762 bool HasToLinkLocalOrIndirectClause = false;
1763 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1764 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1765 bool HasIdentifier = Tok.is(tok::identifier);
1766 if (HasIdentifier) {
1767 // If we see any clause we need a to, link, or local clause.
1768 RequiresToLinkLocalOrIndirectClause = true;
1769 IdentifierInfo *II = Tok.getIdentifierInfo();
1770 StringRef ClauseName = II->getName();
1771 bool IsDeviceTypeClause =
1772 getLangOpts().OpenMP >= 50 &&
1773 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1774
1775 bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1776 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1777
1778 if (DTCI.Indirect && IsIndirectClause) {
1779 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1780 Diag(Tok, diag::err_omp_more_one_clause)
1781 << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)
1782 << getOpenMPClauseName(OMPC_indirect) << 0;
1783 break;
1784 }
1785 bool IsToEnterLinkOrLocalClause =
1786 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1787 assert((!IsDeviceTypeClause || !IsToEnterLinkOrLocalClause) &&
1788 "Cannot be both!");
1789
1790 // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1791 // `enter` clause.
1792 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1793 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1794 break;
1795 }
1796 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1797 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1798 break;
1799 }
1800
1801 // The 'local' clause is only available in OpenMP 6.0.
1802 if (getLangOpts().OpenMP < 60 && ClauseName == "local") {
1803 Diag(Tok, getLangOpts().OpenMP >= 52
1804 ? diag::err_omp_declare_target_unexpected_clause_52
1805 : diag::err_omp_declare_target_unexpected_clause)
1806 << ClauseName
1807 << (getLangOpts().OpenMP >= 51 ? 4
1808 : getLangOpts().OpenMP >= 50 ? 2
1809 : 1);
1810 break;
1811 }
1812
1813 if (!IsDeviceTypeClause && !IsIndirectClause &&
1814 DTCI.Kind == OMPD_begin_declare_target) {
1815 Diag(Tok, getLangOpts().OpenMP >= 52
1816 ? diag::err_omp_declare_target_unexpected_clause_52
1817 : diag::err_omp_declare_target_unexpected_clause)
1818 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
1819 break;
1820 }
1821
1822 if (!IsDeviceTypeClause && !IsToEnterLinkOrLocalClause &&
1823 !IsIndirectClause) {
1824 Diag(Tok, getLangOpts().OpenMP >= 52
1825 ? diag::err_omp_declare_target_unexpected_clause_52
1826 : diag::err_omp_declare_target_unexpected_clause)
1827 << ClauseName
1828 << (getLangOpts().OpenMP > 52 ? 5
1829 : getLangOpts().OpenMP >= 51 ? 4
1830 : getLangOpts().OpenMP >= 50 ? 2
1831 : 1);
1832 break;
1833 }
1834
1835 if (IsToEnterLinkOrLocalClause || IsIndirectClause)
1836 HasToLinkLocalOrIndirectClause = true;
1837
1838 if (IsIndirectClause) {
1839 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1840 break;
1841 continue;
1842 }
1843 // Parse 'device_type' clause and go to next clause if any.
1844 if (IsDeviceTypeClause) {
1845 std::optional<SimpleClauseData> DevTypeData =
1846 parseOpenMPSimpleClause(*this, OMPC_device_type);
1847 if (DevTypeData) {
1848 if (DeviceTypeLoc.isValid()) {
1849 // We already saw another device_type clause, diagnose it.
1850 Diag(DevTypeData->Loc,
1851 diag::warn_omp_more_one_device_type_clause);
1852 break;
1853 }
1854 switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1855 case OMPC_DEVICE_TYPE_any:
1856 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1857 break;
1858 case OMPC_DEVICE_TYPE_host:
1859 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1860 break;
1861 case OMPC_DEVICE_TYPE_nohost:
1862 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1863 break;
1865 llvm_unreachable("Unexpected device_type");
1866 }
1867 DeviceTypeLoc = DevTypeData->Loc;
1868 }
1869 continue;
1870 }
1871 ConsumeToken();
1872 }
1873
1874 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1875 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1876 DeclarationNameInfo NameInfo) {
1877 NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
1878 getCurScope(), SS, NameInfo);
1879 if (!ND)
1880 return;
1881 SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
1882 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1883 if (!FirstMapping)
1884 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1885 << NameInfo.getName();
1886 };
1887 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1888 /*AllowScopeSpecifier=*/true))
1889 break;
1890 }
1891
1892 if (Tok.is(tok::l_paren)) {
1893 Diag(Tok,
1894 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1895 break;
1896 }
1897 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1898 Diag(Tok,
1899 getLangOpts().OpenMP >= 52
1900 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1901 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1902 break;
1903 }
1904
1905 // Consume optional ','.
1906 if (Tok.is(tok::comma))
1907 ConsumeToken();
1908 }
1909
1910 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1911 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1912
1913 // declare target requires at least one clause.
1914 if (DTCI.Kind == OMPD_declare_target && RequiresToLinkLocalOrIndirectClause &&
1915 !HasToLinkLocalOrIndirectClause)
1916 Diag(DTCI.Loc, diag::err_omp_declare_target_missing_required_clause)
1917 << (getLangOpts().OpenMP >= 60 ? 3
1918 : getLangOpts().OpenMP == 52 ? 2
1919 : getLangOpts().OpenMP == 51 ? 1
1920 : 0);
1921
1922 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1923}
1924
1925void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1926 // The last seen token is annot_pragma_openmp_end - need to check for
1927 // extra tokens.
1928 if (Tok.is(tok::annot_pragma_openmp_end))
1929 return;
1930
1931 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1932 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1933 << getOpenMPDirectiveName(DKind, OMPVersion);
1934 while (Tok.isNot(tok::annot_pragma_openmp_end))
1936}
1937
1938void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1939 OpenMPDirectiveKind ExpectedKind,
1940 OpenMPDirectiveKind FoundKind,
1941 SourceLocation BeginLoc,
1942 SourceLocation FoundLoc,
1943 bool SkipUntilOpenMPEnd) {
1944 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1945
1946 if (FoundKind == ExpectedKind) {
1948 skipUntilPragmaOpenMPEnd(ExpectedKind);
1949 return;
1950 }
1951
1952 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1953 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1954 << DiagSelection;
1955 Diag(BeginLoc, diag::note_matching)
1956 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + "'")
1957 .str();
1958 if (SkipUntilOpenMPEnd)
1959 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1960}
1961
1962void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
1963 OpenMPDirectiveKind EndDKind,
1964 SourceLocation DKLoc) {
1965 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
1966 Tok.getLocation(),
1967 /* SkipUntilOpenMPEnd */ false);
1968 // Skip the last annot_pragma_openmp_end.
1969 if (Tok.is(tok::annot_pragma_openmp_end))
1970 ConsumeAnnotationToken();
1971}
1972
1973Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1974 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
1975 DeclSpec::TST TagType, Decl *Tag) {
1976 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
1977 "Not an OpenMP directive!");
1978 ParsingOpenMPDirectiveRAII DirScope(*this);
1979 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1980 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1981
1982 SourceLocation Loc;
1983 OpenMPDirectiveKind DKind;
1984 if (Delayed) {
1985 TentativeParsingAction TPA(*this);
1986 Loc = ConsumeAnnotationToken();
1987 DKind = parseOpenMPDirectiveKind(*this);
1988 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1989 // Need to delay parsing until completion of the parent class.
1990 TPA.Revert();
1991 CachedTokens Toks;
1992 unsigned Cnt = 1;
1993 Toks.push_back(Tok);
1994 while (Cnt && Tok.isNot(tok::eof)) {
1995 (void)ConsumeAnyToken();
1996 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
1997 ++Cnt;
1998 else if (Tok.is(tok::annot_pragma_openmp_end))
1999 --Cnt;
2000 Toks.push_back(Tok);
2001 }
2002 // Skip last annot_pragma_openmp_end.
2003 if (Cnt == 0)
2004 (void)ConsumeAnyToken();
2005 auto *LP = new LateParsedPragma(this, AS);
2006 LP->takeToks(Toks);
2007 getCurrentClass().LateParsedDeclarations.push_back(LP);
2008 return nullptr;
2009 }
2010 TPA.Commit();
2011 } else {
2012 Loc = ConsumeAnnotationToken();
2013 DKind = parseOpenMPDirectiveKind(*this);
2014 }
2015
2016 switch (DKind) {
2017 case OMPD_threadprivate: {
2018 ConsumeToken();
2019 DeclDirectiveListParserHelper Helper(this, DKind);
2020 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2021 /*AllowScopeSpecifier=*/true)) {
2022 skipUntilPragmaOpenMPEnd(DKind);
2023 // Skip the last annot_pragma_openmp_end.
2024 ConsumeAnnotationToken();
2025 return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2026 Loc, Helper.getIdentifiers());
2027 }
2028 break;
2029 }
2030 case OMPD_groupprivate: {
2031 ConsumeToken();
2032 DeclDirectiveListParserHelper Helper(this, DKind);
2033 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2034 /*AllowScopeSpecifier=*/true)) {
2035 skipUntilPragmaOpenMPEnd(DKind);
2036 // Skip the last annot_pragma_openmp_end.
2037 ConsumeAnnotationToken();
2038 return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2039 Loc, Helper.getIdentifiers());
2040 }
2041 break;
2042 }
2043 case OMPD_allocate: {
2044 ConsumeToken();
2045 DeclDirectiveListParserHelper Helper(this, DKind);
2046 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2047 /*AllowScopeSpecifier=*/true)) {
2048 SmallVector<OMPClause *, 1> Clauses;
2049 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2050 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
2051 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2052 OpenMPClauseKind CKind =
2053 Tok.isAnnotation() ? OMPC_unknown
2054 : getOpenMPClauseKind(PP.getSpelling(Tok));
2055 Actions.OpenMP().StartOpenMPClause(CKind);
2056 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2057 !SeenClauses[unsigned(CKind)]);
2058 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2060 SeenClauses[unsigned(CKind)] = true;
2061 if (Clause != nullptr)
2062 Clauses.push_back(Clause);
2063 if (Tok.is(tok::annot_pragma_openmp_end)) {
2064 Actions.OpenMP().EndOpenMPClause();
2065 break;
2066 }
2067 // Skip ',' if any.
2068 if (Tok.is(tok::comma))
2069 ConsumeToken();
2070 Actions.OpenMP().EndOpenMPClause();
2071 }
2072 skipUntilPragmaOpenMPEnd(DKind);
2073 }
2074 // Skip the last annot_pragma_openmp_end.
2075 ConsumeAnnotationToken();
2076 return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2077 Loc, Helper.getIdentifiers(), Clauses);
2078 }
2079 break;
2080 }
2081 case OMPD_requires: {
2082 SourceLocation StartLoc = ConsumeToken();
2083 SmallVector<OMPClause *, 5> Clauses;
2084 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2085 if (Tok.is(tok::annot_pragma_openmp_end)) {
2086 Diag(Tok, diag::err_omp_expected_clause)
2087 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2088 break;
2089 }
2090 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2091 OpenMPClauseKind CKind = Tok.isAnnotation()
2092 ? OMPC_unknown
2093 : getOpenMPClauseKind(PP.getSpelling(Tok));
2094 Actions.OpenMP().StartOpenMPClause(CKind);
2095 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
2096 !SeenClauses[unsigned(CKind)]);
2097 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2099 SeenClauses[unsigned(CKind)] = true;
2100 if (Clause != nullptr)
2101 Clauses.push_back(Clause);
2102 if (Tok.is(tok::annot_pragma_openmp_end)) {
2103 Actions.OpenMP().EndOpenMPClause();
2104 break;
2105 }
2106 // Skip ',' if any.
2107 if (Tok.is(tok::comma))
2108 ConsumeToken();
2109 Actions.OpenMP().EndOpenMPClause();
2110 }
2111 // Consume final annot_pragma_openmp_end
2112 if (Clauses.empty()) {
2113 Diag(Tok, diag::err_omp_expected_clause)
2114 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
2115 ConsumeAnnotationToken();
2116 return nullptr;
2117 }
2118 ConsumeAnnotationToken();
2119 return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
2120 }
2121 case OMPD_error: {
2122 SmallVector<OMPClause *, 1> Clauses;
2123 SourceLocation StartLoc = ConsumeToken();
2124 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2125 Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2126 SourceLocation(),
2127 /*InExContext = */ false);
2128 break;
2129 }
2130 case OMPD_assumes:
2131 case OMPD_begin_assumes:
2132 ParseOpenMPAssumesDirective(DKind, ConsumeToken());
2133 break;
2134 case OMPD_end_assumes:
2135 ParseOpenMPEndAssumesDirective(ConsumeToken());
2136 break;
2137 case OMPD_declare_reduction:
2138 ConsumeToken();
2139 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2140 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2141 // Skip the last annot_pragma_openmp_end.
2142 ConsumeAnnotationToken();
2143 return Res;
2144 }
2145 break;
2146 case OMPD_declare_mapper: {
2147 ConsumeToken();
2148 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2149 // Skip the last annot_pragma_openmp_end.
2150 ConsumeAnnotationToken();
2151 return Res;
2152 }
2153 break;
2154 }
2155 case OMPD_begin_declare_variant: {
2156 ConsumeToken();
2158 // Skip the last annot_pragma_openmp_end.
2159 if (!isEofOrEom())
2160 ConsumeAnnotationToken();
2161 }
2162 return nullptr;
2163 }
2164 case OMPD_end_declare_variant: {
2165 ConsumeToken();
2166 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2167 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2168 else
2169 Diag(Loc, diag::err_expected_begin_declare_variant);
2170 // Skip the last annot_pragma_openmp_end.
2171 ConsumeAnnotationToken();
2172 return nullptr;
2173 }
2174 case OMPD_declare_variant:
2175 case OMPD_declare_simd: {
2176 // The syntax is:
2177 // { #pragma omp declare {simd|variant} }
2178 // <function-declaration-or-definition>
2179 //
2180 CachedTokens Toks;
2181 Toks.push_back(Tok);
2182 ConsumeToken();
2183 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2184 Toks.push_back(Tok);
2186 }
2187 Toks.push_back(Tok);
2189
2190 DeclGroupPtrTy Ptr;
2191 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2192 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2193 TagType, Tag);
2194 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
2195 // Here we expect to see some function declaration.
2196 if (AS == AS_none) {
2197 assert(TagType == DeclSpec::TST_unspecified);
2198 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2199 MaybeParseCXX11Attributes(Attrs);
2200 ParsingDeclSpec PDS(*this);
2201 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2202 } else {
2203 Ptr =
2204 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
2205 }
2206 }
2207 if (!Ptr) {
2208 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2209 << (DKind == OMPD_declare_simd ? 0 : 1);
2210 return DeclGroupPtrTy();
2211 }
2212 if (DKind == OMPD_declare_simd)
2213 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2214 assert(DKind == OMPD_declare_variant &&
2215 "Expected declare variant directive only");
2216 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2217 return Ptr;
2218 }
2219 case OMPD_begin_declare_target:
2220 case OMPD_declare_target: {
2221 SourceLocation DTLoc = ConsumeAnyToken();
2222 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2223 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2224 if (DKind == OMPD_declare_target && !HasClauses &&
2225 getLangOpts().OpenMP >= 52)
2226 Diag(DTLoc, diag::warn_omp_deprecated_declare_target_delimited_form);
2227 if (HasClauses)
2228 ParseOMPDeclareTargetClauses(DTCI);
2229 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2230 !HasClauses ||
2231 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2232
2233 // Skip the last annot_pragma_openmp_end.
2235
2236 if (HasImplicitMappings) {
2237 Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
2238 return nullptr;
2239 }
2240
2241 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2242 llvm::SmallVector<Decl *, 4> Decls;
2243 for (auto &It : DTCI.ExplicitlyMapped)
2244 Decls.push_back(It.first);
2245 return Actions.BuildDeclaratorGroup(Decls);
2246 }
2247 case OMPD_end_declare_target: {
2248 if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2249 Diag(Tok, diag::err_omp_unexpected_directive)
2250 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2251 break;
2252 }
2253 const SemaOpenMP::DeclareTargetContextInfo &DTCI =
2254 Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
2255 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2256 return nullptr;
2257 }
2258 case OMPD_assume: {
2259 Diag(Tok, diag::err_omp_unexpected_directive)
2260 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2261 break;
2262 }
2263 case OMPD_unknown:
2264 Diag(Tok, diag::err_omp_unknown_directive);
2265 break;
2266 default:
2267 switch (getDirectiveCategory(DKind)) {
2268 case Category::Executable:
2269 case Category::Meta:
2270 case Category::Subsidiary:
2271 case Category::Utility:
2272 Diag(Tok, diag::err_omp_unexpected_directive)
2273 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2274 break;
2275 case Category::Declarative:
2276 case Category::Informational:
2277 break;
2278 }
2279 }
2280 while (Tok.isNot(tok::annot_pragma_openmp_end))
2283 return nullptr;
2284}
2285
2286StmtResult Parser::ParseOpenMPExecutableDirective(
2287 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2288 bool ReadDirectiveWithinMetadirective) {
2289 assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2290 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2291
2292 bool HasAssociatedStatement = true;
2293 Association Assoc = getDirectiveAssociation(DKind);
2294
2295 // OMPD_ordered has None as association, but it comes in two variants,
2296 // the second of which is associated with a block.
2297 // OMPD_scan and OMPD_section are both "separating", but section is treated
2298 // as if it was associated with a statement, while scan is not.
2299 if (DKind != OMPD_ordered && DKind != OMPD_section &&
2300 (Assoc == Association::None || Assoc == Association::Separating)) {
2301 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2302 ParsedStmtContext()) {
2303 Diag(Tok, diag::err_omp_immediate_directive)
2304 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2305 if (DKind == OMPD_error) {
2306 SkipUntil(tok::annot_pragma_openmp_end);
2307 return StmtError();
2308 }
2309 }
2310 HasAssociatedStatement = false;
2311 }
2312
2313 SourceLocation EndLoc;
2314 SmallVector<OMPClause *, 5> Clauses;
2315 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2316 DeclarationNameInfo DirName;
2317 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2318 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2320
2321 // Special processing for flush and depobj clauses.
2322 Token ImplicitTok;
2323 bool ImplicitClauseAllowed = false;
2324 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2325 ImplicitTok = Tok;
2326 ImplicitClauseAllowed = true;
2327 }
2328 ConsumeToken();
2329 // Parse directive name of the 'critical' directive if any.
2330 if (DKind == OMPD_critical) {
2331 BalancedDelimiterTracker T(*this, tok::l_paren,
2332 tok::annot_pragma_openmp_end);
2333 if (!T.consumeOpen()) {
2334 if (Tok.isAnyIdentifier()) {
2335 DirName =
2336 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2338 } else {
2339 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2340 }
2341 T.consumeClose();
2342 }
2343 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2344 CancelRegion = parseOpenMPDirectiveKind(*this);
2345 if (Tok.isNot(tok::annot_pragma_openmp_end))
2347 }
2348
2349 if (isOpenMPLoopDirective(DKind))
2350 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2351 if (isOpenMPSimdDirective(DKind))
2352 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2353 ParseScope OMPDirectiveScope(this, ScopeFlags);
2354 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2355 Loc);
2356
2357 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2358 // If we are parsing for a directive within a metadirective, the directive
2359 // ends with a ')'.
2360 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2361 while (Tok.isNot(tok::annot_pragma_openmp_end))
2363 break;
2364 }
2365 bool HasImplicitClause = false;
2366 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2367 HasImplicitClause = true;
2368 // Push copy of the current token back to stream to properly parse
2369 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2370 PP.EnterToken(Tok, /*IsReinject*/ true);
2371 PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2373 }
2374 OpenMPClauseKind CKind = Tok.isAnnotation()
2375 ? OMPC_unknown
2376 : getOpenMPClauseKind(PP.getSpelling(Tok));
2377 if (HasImplicitClause) {
2378 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2379 if (DKind == OMPD_flush) {
2380 CKind = OMPC_flush;
2381 } else {
2382 assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2383 CKind = OMPC_depobj;
2384 }
2385 }
2386 // No more implicit clauses allowed.
2387 ImplicitClauseAllowed = false;
2388 Actions.OpenMP().StartOpenMPClause(CKind);
2389 HasImplicitClause = false;
2390 OMPClause *Clause =
2391 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2392 SeenClauses[unsigned(CKind)] = true;
2393 if (Clause)
2394 Clauses.push_back(Clause);
2395
2396 // Skip ',' if any.
2397 if (Tok.is(tok::comma))
2398 ConsumeToken();
2399 Actions.OpenMP().EndOpenMPClause();
2400 }
2401 // End location of the directive.
2402 EndLoc = Tok.getLocation();
2403 // Consume final annot_pragma_openmp_end.
2404 ConsumeAnnotationToken();
2405
2406 if (DKind == OMPD_ordered) {
2407 // If the depend or doacross clause is specified, the ordered construct
2408 // is a stand-alone directive.
2409 for (auto CK : {OMPC_depend, OMPC_doacross}) {
2410 if (SeenClauses[unsigned(CK)]) {
2411 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2412 ParsedStmtContext()) {
2413 Diag(Loc, diag::err_omp_immediate_directive)
2414 << getOpenMPDirectiveName(DKind, OMPVersion) << 1
2415 << getOpenMPClauseName(CK);
2416 }
2417 HasAssociatedStatement = false;
2418 }
2419 }
2420 }
2421
2422 if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
2423 !SeenClauses[unsigned(OMPC_sizes)]) {
2424 Diag(Loc, diag::err_omp_required_clause)
2425 << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";
2426 }
2427
2428 StmtResult AssociatedStmt;
2429 if (HasAssociatedStatement) {
2430 // The body is a block scope like in Lambdas and Blocks.
2431 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2432 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2433 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2434 // should have at least one compound statement scope within it.
2435 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2436 {
2437 Sema::CompoundScopeRAII Scope(Actions);
2438 AssociatedStmt = ParseStatement();
2439
2440 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2441 getLangOpts().OpenMPIRBuilder)
2442 AssociatedStmt =
2443 Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2444 }
2445 AssociatedStmt =
2446 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2447 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2448 DKind == OMPD_target_exit_data) {
2449 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2450 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2451 Actions.ActOnCompoundStmt(Loc, Loc, {},
2452 /*isStmtExpr=*/false));
2453 AssociatedStmt =
2454 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2455 }
2456
2457 StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
2458 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2459
2460 // Exit scope.
2461 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2462 OMPDirectiveScope.Exit();
2463
2464 return Directive;
2465}
2466
2467StmtResult Parser::ParseOpenMPInformationalDirective(
2468 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2469 bool ReadDirectiveWithinMetadirective) {
2470 assert(isOpenMPInformationalDirective(DKind) &&
2471 "Unexpected directive category");
2472
2473 bool HasAssociatedStatement = true;
2474
2475 SmallVector<OMPClause *, 5> Clauses;
2476 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2477 DeclarationNameInfo DirName;
2478 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2480 ParseScope OMPDirectiveScope(this, ScopeFlags);
2481
2482 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2483 Loc);
2484
2485 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2486 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2487 while (Tok.isNot(tok::annot_pragma_openmp_end))
2489 break;
2490 }
2491
2492 OpenMPClauseKind CKind = Tok.isAnnotation()
2493 ? OMPC_unknown
2494 : getOpenMPClauseKind(PP.getSpelling(Tok));
2495 Actions.OpenMP().StartOpenMPClause(CKind);
2496 OMPClause *Clause =
2497 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2498 SeenClauses[unsigned(CKind)] = true;
2499 if (Clause)
2500 Clauses.push_back(Clause);
2501
2502 if (Tok.is(tok::comma))
2503 ConsumeToken();
2504 Actions.OpenMP().EndOpenMPClause();
2505 }
2506
2507 SourceLocation EndLoc = Tok.getLocation();
2508 ConsumeAnnotationToken();
2509
2510 StmtResult AssociatedStmt;
2511 if (HasAssociatedStatement) {
2512 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2513 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2514 {
2515 Sema::CompoundScopeRAII Scope(Actions);
2516 AssociatedStmt = ParseStatement();
2517 }
2518 AssociatedStmt =
2519 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2520 }
2521
2522 StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
2523 DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2524
2525 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2526 OMPDirectiveScope.Exit();
2527
2528 return Directive;
2529}
2530
2531StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2532 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2533 if (!ReadDirectiveWithinMetadirective)
2534 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2535 "Not an OpenMP directive!");
2536 ParsingOpenMPDirectiveRAII DirScope(*this);
2537 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2538 SourceLocation Loc = ReadDirectiveWithinMetadirective
2539 ? Tok.getLocation()
2540 : ConsumeAnnotationToken();
2541 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2543 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2544 Diag(Tok, diag::err_omp_unknown_directive);
2545 return StmtError();
2546 }
2547
2549
2550 bool IsExecutable = [&]() {
2551 if (DKind == OMPD_error) // OMPD_error is handled as executable
2552 return true;
2553 auto Res = getDirectiveCategory(DKind);
2554 return Res == Category::Executable || Res == Category::Subsidiary;
2555 }();
2556
2557 if (IsExecutable) {
2558 Directive = ParseOpenMPExecutableDirective(
2559 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2560 assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2561 return Directive;
2562 }
2563
2564 switch (DKind) {
2565 case OMPD_nothing:
2566 ConsumeToken();
2567 // If we are parsing the directive within a metadirective, the directive
2568 // ends with a ')'.
2569 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
2570 while (Tok.isNot(tok::annot_pragma_openmp_end))
2572 else
2573 skipUntilPragmaOpenMPEnd(DKind);
2574 if (Tok.is(tok::annot_pragma_openmp_end))
2575 ConsumeAnnotationToken();
2576 // return an empty statement
2577 return StmtEmpty();
2578 case OMPD_metadirective: {
2579 ConsumeToken();
2580 SmallVector<VariantMatchInfo, 4> VMIs;
2581
2582 // First iteration of parsing all clauses of metadirective.
2583 // This iteration only parses and collects all context selector ignoring the
2584 // associated directives.
2585 TentativeParsingAction TPA(*this);
2586 ASTContext &ASTContext = Actions.getASTContext();
2587
2588 BalancedDelimiterTracker T(*this, tok::l_paren,
2589 tok::annot_pragma_openmp_end);
2590 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2591 OpenMPClauseKind CKind = Tok.isAnnotation()
2592 ? OMPC_unknown
2593 : getOpenMPClauseKind(PP.getSpelling(Tok));
2594 // Check if the clause is unrecognized.
2595 if (CKind == OMPC_unknown) {
2596 Diag(Tok, diag::err_omp_expected_clause) << "metadirective";
2597 TPA.Revert();
2598 SkipUntil(tok::annot_pragma_openmp_end);
2599 return Directive;
2600 }
2601 if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)
2602 Diag(Tok, diag::err_omp_unexpected_clause)
2603 << getOpenMPClauseName(CKind) << "metadirective";
2604 if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)
2605 Diag(Tok, diag::warn_omp_default_deprecated);
2606
2607 SourceLocation Loc = ConsumeToken();
2608
2609 // Parse '('.
2610 if (T.expectAndConsume(diag::err_expected_lparen_after,
2611 getOpenMPClauseName(CKind).data())) {
2612 TPA.Revert();
2613 SkipUntil(tok::annot_pragma_openmp_end);
2614 return Directive;
2615 }
2616
2617 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2618 if (CKind == OMPC_when) {
2619 // parse and get OMPTraitInfo to pass to the When clause
2620 parseOMPContextSelectors(Loc, TI);
2621 if (TI.Sets.size() == 0) {
2622 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2623 TPA.Commit();
2624 return Directive;
2625 }
2626
2627 // Parse ':'
2628 if (Tok.is(tok::colon))
2630 else {
2631 Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2632 TPA.Commit();
2633 return Directive;
2634 }
2635 }
2636
2637 // Skip Directive for now. We will parse directive in the second iteration
2638 int paren = 0;
2639 while (Tok.isNot(tok::r_paren) || paren != 0) {
2640 if (Tok.is(tok::l_paren))
2641 paren++;
2642 if (Tok.is(tok::r_paren))
2643 paren--;
2644 if (Tok.is(tok::annot_pragma_openmp_end)) {
2645 Diag(Tok, diag::err_omp_expected_punc)
2646 << getOpenMPClauseName(CKind) << 0;
2647 TPA.Commit();
2648 return Directive;
2649 }
2651 }
2652 // Parse ')'
2653 if (Tok.is(tok::r_paren))
2654 T.consumeClose();
2655
2656 VariantMatchInfo VMI;
2657 TI.getAsVariantMatchInfo(ASTContext, VMI);
2658
2659 VMIs.push_back(VMI);
2660 }
2661
2662 TPA.Revert();
2663 // End of the first iteration. Parser is reset to the start of metadirective
2664
2665 std::function<void(StringRef)> DiagUnknownTrait =
2666 [this, Loc](StringRef ISATrait) {
2667 // TODO Track the selector locations in a way that is accessible here
2668 // to improve the diagnostic location.
2669 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2670 };
2671 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2672 /* CurrentFunctionDecl */ nullptr,
2673 ArrayRef<llvm::omp::TraitProperty>(),
2674 Actions.OpenMP().getOpenMPDeviceNum());
2675
2676 // A single match is returned for OpenMP 5.0
2677 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2678
2679 int Idx = 0;
2680 // In OpenMP 5.0 metadirective is either replaced by another directive or
2681 // ignored.
2682 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2683 // found by getBestWhenMatchForContext.
2684 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2685 // OpenMP 5.0 implementation - Skip to the best index found.
2686 if (Idx++ != BestIdx) {
2687 ConsumeToken(); // Consume clause name
2688 T.consumeOpen(); // Consume '('
2689 int paren = 0;
2690 // Skip everything inside the clause
2691 while (Tok.isNot(tok::r_paren) || paren != 0) {
2692 if (Tok.is(tok::l_paren))
2693 paren++;
2694 if (Tok.is(tok::r_paren))
2695 paren--;
2697 }
2698 // Parse ')'
2699 if (Tok.is(tok::r_paren))
2700 T.consumeClose();
2701 continue;
2702 }
2703
2704 OpenMPClauseKind CKind = Tok.isAnnotation()
2705 ? OMPC_unknown
2706 : getOpenMPClauseKind(PP.getSpelling(Tok));
2707 SourceLocation Loc = ConsumeToken();
2708
2709 // Parse '('.
2710 T.consumeOpen();
2711
2712 // Skip ContextSelectors for when clause
2713 if (CKind == OMPC_when) {
2714 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2715 // parse and skip the ContextSelectors
2716 parseOMPContextSelectors(Loc, TI);
2717
2718 // Parse ':'
2720 }
2721
2722 // If no directive is passed, skip in OpenMP 5.0.
2723 // TODO: Generate nothing directive from OpenMP 5.1.
2724 if (Tok.is(tok::r_paren)) {
2725 SkipUntil(tok::annot_pragma_openmp_end);
2726 break;
2727 }
2728
2729 // Parse Directive
2730 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2731 StmtCtx,
2732 /*ReadDirectiveWithinMetadirective=*/true);
2733 break;
2734 }
2735 // If no match is found and no otherwise clause is present, skip
2736 // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
2737 // if one was specified without an associated directive variant.
2738 if (BestIdx == -1 && Idx > 0) {
2739 assert(Tok.is(tok::annot_pragma_openmp_end) &&
2740 "Expecting the end of the pragma here");
2741 ConsumeAnnotationToken();
2742 return StmtEmpty();
2743 }
2744 break;
2745 }
2746 case OMPD_threadprivate: {
2747 // FIXME: Should this be permitted in C++?
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().ActOnOpenMPThreadprivateDirective(
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_groupprivate: {
2766 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2767 ParsedStmtContext()) {
2768 Diag(Tok, diag::err_omp_immediate_directive)
2769 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2770 }
2771 ConsumeToken();
2772 DeclDirectiveListParserHelper Helper(this, DKind);
2773 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2774 /*AllowScopeSpecifier=*/false)) {
2775 skipUntilPragmaOpenMPEnd(DKind);
2776 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2777 Loc, Helper.getIdentifiers());
2778 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2779 }
2780 SkipUntil(tok::annot_pragma_openmp_end);
2781 break;
2782 }
2783 case OMPD_allocate: {
2784 // FIXME: Should this be permitted in C++?
2785 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2786 ParsedStmtContext()) {
2787 Diag(Tok, diag::err_omp_immediate_directive)
2788 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
2789 }
2790 ConsumeToken();
2791 DeclDirectiveListParserHelper Helper(this, DKind);
2792 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2793 /*AllowScopeSpecifier=*/false)) {
2794 SmallVector<OMPClause *, 1> Clauses;
2795 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2796 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2797 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2798 OpenMPClauseKind CKind =
2799 Tok.isAnnotation() ? OMPC_unknown
2800 : getOpenMPClauseKind(PP.getSpelling(Tok));
2801 Actions.OpenMP().StartOpenMPClause(CKind);
2802 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2803 !SeenClauses[unsigned(CKind)]);
2804 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2806 SeenClauses[unsigned(CKind)] = true;
2807 if (Clause != nullptr)
2808 Clauses.push_back(Clause);
2809 if (Tok.is(tok::annot_pragma_openmp_end)) {
2810 Actions.OpenMP().EndOpenMPClause();
2811 break;
2812 }
2813 // Skip ',' if any.
2814 if (Tok.is(tok::comma))
2815 ConsumeToken();
2816 Actions.OpenMP().EndOpenMPClause();
2817 }
2818 skipUntilPragmaOpenMPEnd(DKind);
2819 }
2820 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
2821 Loc, Helper.getIdentifiers(), Clauses);
2822 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2823 }
2824 SkipUntil(tok::annot_pragma_openmp_end);
2825 break;
2826 }
2827 case OMPD_declare_reduction:
2828 ConsumeToken();
2829 if (DeclGroupPtrTy Res =
2830 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2831 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2833 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2834 } else {
2835 SkipUntil(tok::annot_pragma_openmp_end);
2836 }
2837 break;
2838 case OMPD_declare_mapper: {
2839 ConsumeToken();
2840 if (DeclGroupPtrTy Res =
2841 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2842 // Skip the last annot_pragma_openmp_end.
2843 ConsumeAnnotationToken();
2844 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2845 } else {
2846 SkipUntil(tok::annot_pragma_openmp_end);
2847 }
2848 break;
2849 }
2850 case OMPD_declare_target: {
2851 SourceLocation DTLoc = ConsumeAnyToken();
2852 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2853 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2854 if (HasClauses)
2855 ParseOMPDeclareTargetClauses(DTCI);
2856 bool HasImplicitMappings =
2857 !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2858
2859 if (HasImplicitMappings) {
2860 Diag(Tok, diag::err_omp_unexpected_directive)
2861 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2862 SkipUntil(tok::annot_pragma_openmp_end);
2863 break;
2864 }
2865
2866 // Skip the last annot_pragma_openmp_end.
2868
2869 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2870 break;
2871 }
2872 case OMPD_begin_declare_variant: {
2873 ConsumeToken();
2875 // Skip the last annot_pragma_openmp_end.
2876 if (!isEofOrEom())
2877 ConsumeAnnotationToken();
2878 }
2879 return Directive;
2880 }
2881 case OMPD_end_declare_variant: {
2882 ConsumeToken();
2883 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2884 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2885 else
2886 Diag(Loc, diag::err_expected_begin_declare_variant);
2887 ConsumeAnnotationToken();
2888 break;
2889 }
2890 case OMPD_declare_simd:
2891 case OMPD_begin_declare_target:
2892 case OMPD_end_declare_target:
2893 case OMPD_requires:
2894 case OMPD_declare_variant:
2895 Diag(Tok, diag::err_omp_unexpected_directive)
2896 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
2897 SkipUntil(tok::annot_pragma_openmp_end);
2898 break;
2899 case OMPD_assume: {
2900 ConsumeToken();
2901 Directive = ParseOpenMPInformationalDirective(
2902 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2903 assert(!Directive.isUnset() &&
2904 "Informational directive remains unprocessed");
2905 return Directive;
2906 }
2907 case OMPD_unknown:
2908 default:
2909 Diag(Tok, diag::err_omp_unknown_directive);
2910 SkipUntil(tok::annot_pragma_openmp_end);
2911 break;
2912 }
2913 return Directive;
2914}
2915
2916bool Parser::ParseOpenMPSimpleVarList(
2918 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2919 &Callback,
2920 bool AllowScopeSpecifier) {
2921 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2922 // Parse '('.
2923 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2924 if (T.expectAndConsume(diag::err_expected_lparen_after,
2925 getOpenMPDirectiveName(Kind, OMPVersion).data()))
2926 return true;
2927 bool IsCorrect = true;
2928 bool NoIdentIsFound = true;
2929
2930 // Read tokens while ')' or annot_pragma_openmp_end is not found.
2931 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2932 CXXScopeSpec SS;
2933 UnqualifiedId Name;
2934 // Read var name.
2935 Token PrevTok = Tok;
2936 NoIdentIsFound = false;
2937
2938 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2939 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2940 /*ObjectHasErrors=*/false, false)) {
2941 IsCorrect = false;
2942 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2944 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2945 /*ObjectHadErrors=*/false, false, false,
2946 false, false, nullptr, Name)) {
2947 IsCorrect = false;
2948 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2950 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2951 Tok.isNot(tok::annot_pragma_openmp_end)) {
2952 IsCorrect = false;
2953 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2955 Diag(PrevTok.getLocation(), diag::err_expected)
2956 << tok::identifier
2957 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2958 } else {
2959 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2960 }
2961 // Consume ','.
2962 if (Tok.is(tok::comma)) {
2963 ConsumeToken();
2964 }
2965 }
2966
2967 if (NoIdentIsFound) {
2968 Diag(Tok, diag::err_expected) << tok::identifier;
2969 IsCorrect = false;
2970 }
2971
2972 // Parse ')'.
2973 IsCorrect = !T.consumeClose() && IsCorrect;
2974
2975 return !IsCorrect;
2976}
2977
2978OMPClause *Parser::ParseOpenMPSizesClause() {
2979 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
2980 SmallVector<Expr *, 4> ValExprs;
2981 if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
2982 ValExprs))
2983 return nullptr;
2984
2985 return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
2986 OpenLoc, CloseLoc);
2987}
2988
2989OMPClause *Parser::ParseOpenMPLoopRangeClause() {
2990 SourceLocation ClauseNameLoc = ConsumeToken();
2991 SourceLocation FirstLoc, CountLoc;
2992
2993 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2994 if (T.consumeOpen()) {
2995 Diag(Tok, diag::err_expected) << tok::l_paren;
2996 return nullptr;
2997 }
2998
2999 FirstLoc = Tok.getLocation();
3001 if (!FirstVal.isUsable()) {
3002 T.skipToEnd();
3003 return nullptr;
3004 }
3005
3006 ExpectAndConsume(tok::comma);
3007
3008 CountLoc = Tok.getLocation();
3010 if (!CountVal.isUsable()) {
3011 T.skipToEnd();
3012 return nullptr;
3013 }
3014
3015 T.consumeClose();
3016
3017 return Actions.OpenMP().ActOnOpenMPLoopRangeClause(
3018 FirstVal.get(), CountVal.get(), ClauseNameLoc, T.getOpenLocation(),
3019 FirstLoc, CountLoc, T.getCloseLocation());
3020}
3021
3022OMPClause *Parser::ParseOpenMPPermutationClause() {
3023 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3024 SmallVector<Expr *> ArgExprs;
3025 if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,
3026 CloseLoc, ArgExprs,
3027 /*ReqIntConst=*/true))
3028 return nullptr;
3029
3030 return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,
3031 OpenLoc, CloseLoc);
3032}
3033
3034OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3035 SourceLocation Loc = Tok.getLocation();
3037
3038 // Parse '('.
3039 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3040 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
3041 return nullptr;
3042 SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
3043 do {
3044 // Parse 'traits(expr) : Allocator' for >=5.2
3045 if (getLangOpts().OpenMP >= 52 && Tok.is(tok::identifier) &&
3046 Tok.getIdentifierInfo()->getName() == "traits") {
3047
3048 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3049
3050 ConsumeToken();
3051
3052 // Parse '(' <expr> ')'
3053 BalancedDelimiterTracker TraitParens(*this, tok::l_paren,
3054 tok::annot_pragma_openmp_end);
3055 TraitParens.consumeOpen();
3056 ExprResult AllocatorTraits =
3057 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3058 TraitParens.consumeClose();
3059
3060 if (AllocatorTraits.isInvalid()) {
3061 SkipUntil(
3062 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3064 break;
3065 }
3066
3067 // Expect ':'
3068 if (Tok.isNot(tok::colon)) {
3069 Diag(Tok, diag::err_expected) << tok::colon;
3070 SkipUntil(
3071 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3073 continue;
3074 }
3075 ConsumeToken();
3076
3077 CXXScopeSpec SS;
3078 Token Replacement;
3079 ExprResult AllocatorExpr =
3080 getLangOpts().CPlusPlus
3081 ? ParseCXXIdExpression()
3082 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
3083 Replacement);
3084
3085 if (AllocatorExpr.isInvalid()) {
3086 SkipUntil(
3087 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3089 break;
3090 }
3091
3092 D.Allocator = AllocatorExpr.get();
3093 D.AllocatorTraits = AllocatorTraits.get();
3094 D.LParenLoc = TraitParens.getOpenLocation();
3095 D.RParenLoc = TraitParens.getCloseLocation();
3096
3097 // Separator handling(;)
3098 if (Tok.is(tok::comma)) {
3099 // In 5.2, comma is invalid
3100 Diag(Tok.getLocation(), diag::err_omp_allocator_comma_separator)
3101 << FixItHint::CreateReplacement(Tok.getLocation(), ";");
3103 } else if (Tok.is(tok::semi)) {
3104 ConsumeAnyToken(); // valid separator
3105 }
3106
3107 continue;
3108 }
3109
3110 // Parse 'Allocator(expr)' for <5.2
3111 CXXScopeSpec SS;
3112 Token Replacement;
3113 ExprResult Allocator =
3114 getLangOpts().CPlusPlus
3115 ? ParseCXXIdExpression()
3116 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
3117 Replacement);
3118 if (Allocator.isInvalid()) {
3119 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3120 StopBeforeMatch);
3121 break;
3122 }
3123 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3124 D.Allocator = Allocator.get();
3125 if (Tok.is(tok::l_paren)) {
3126 BalancedDelimiterTracker T(*this, tok::l_paren,
3127 tok::annot_pragma_openmp_end);
3128 T.consumeOpen();
3129 ExprResult AllocatorTraits =
3130 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3131 T.consumeClose();
3132 if (AllocatorTraits.isInvalid()) {
3133 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3134 StopBeforeMatch);
3135 break;
3136 }
3137 D.AllocatorTraits = AllocatorTraits.get();
3138 D.LParenLoc = T.getOpenLocation();
3139 D.RParenLoc = T.getCloseLocation();
3140
3141 // Deprecation diagnostic in >= 5.2
3142 if (getLangOpts().OpenMP >= 52) {
3143 Diag(Loc, diag::err_omp_deprecate_old_syntax)
3144 << "allocator(expr)" // %0: old form
3145 << "uses_allocators" // %1: clause name
3146 << "traits(expr): alloc"; // %2: suggested new form
3147 }
3148 }
3149 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3150 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
3151 // Parse ','
3152 if (Tok.is(tok::comma))
3153 ConsumeAnyToken();
3154 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
3155 T.consumeClose();
3156 return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3157 Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
3158}
3159
3160OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3161 OpenMPClauseKind CKind, bool FirstClause) {
3162 OMPClauseKind = CKind;
3163 OMPClause *Clause = nullptr;
3164 bool ErrorFound = false;
3165 bool WrongDirective = false;
3166 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
3167
3168 // Check if clause is allowed for the given directive.
3169 if (CKind != OMPC_unknown &&
3170 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
3171 Diag(Tok, diag::err_omp_unexpected_clause)
3172 << getOpenMPClauseName(CKind)
3173 << getOpenMPDirectiveName(DKind, OMPVersion);
3174 ErrorFound = true;
3175 WrongDirective = true;
3176 }
3177
3178 switch (CKind) {
3179 case OMPC_final:
3180 case OMPC_num_threads:
3181 case OMPC_safelen:
3182 case OMPC_simdlen:
3183 case OMPC_collapse:
3184 case OMPC_ordered:
3185 case OMPC_priority:
3186 case OMPC_grainsize:
3187 case OMPC_num_tasks:
3188 case OMPC_hint:
3189 case OMPC_allocator:
3190 case OMPC_depobj:
3191 case OMPC_detach:
3192 case OMPC_novariants:
3193 case OMPC_nocontext:
3194 case OMPC_filter:
3195 case OMPC_partial:
3196 case OMPC_align:
3197 case OMPC_message:
3198 case OMPC_ompx_dyn_cgroup_mem:
3199 case OMPC_dyn_groupprivate:
3200 case OMPC_transparent:
3201 // OpenMP [2.5, Restrictions]
3202 // At most one num_threads clause can appear on the directive.
3203 // OpenMP [2.8.1, simd construct, Restrictions]
3204 // Only one safelen clause can appear on a simd directive.
3205 // Only one simdlen clause can appear on a simd directive.
3206 // Only one collapse clause can appear on a simd directive.
3207 // OpenMP [2.11.1, task Construct, Restrictions]
3208 // At most one if clause can appear on the directive.
3209 // At most one final clause can appear on the directive.
3210 // OpenMP [teams Construct, Restrictions]
3211 // At most one num_teams clause can appear on the directive.
3212 // At most one thread_limit clause can appear on the directive.
3213 // OpenMP [2.9.1, task Construct, Restrictions]
3214 // At most one priority clause can appear on the directive.
3215 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3216 // At most one grainsize clause can appear on the directive.
3217 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3218 // At most one num_tasks clause can appear on the directive.
3219 // OpenMP [2.11.3, allocate Directive, Restrictions]
3220 // At most one allocator clause can appear on the directive.
3221 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3222 // At most one detach clause can appear on the directive.
3223 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3224 // At most one novariants clause can appear on a dispatch directive.
3225 // At most one nocontext clause can appear on a dispatch directive.
3226 // OpenMP [5.1, error directive, Restrictions]
3227 // At most one message clause can appear on the directive
3228 if (!FirstClause) {
3229 Diag(Tok, diag::err_omp_more_one_clause)
3230 << getOpenMPDirectiveName(DKind, OMPVersion)
3231 << getOpenMPClauseName(CKind) << 0;
3232 ErrorFound = true;
3233 }
3234
3235 if (CKind == OMPC_transparent && PP.LookAhead(0).isNot(tok::l_paren)) {
3236 SourceLocation Loc = ConsumeToken();
3237 SourceLocation LLoc = Tok.getLocation();
3238 Clause = Actions.OpenMP().ActOnOpenMPTransparentClause(nullptr, LLoc,
3239 LLoc, Loc);
3240 break;
3241 }
3242 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3243 PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3244 Clause = ParseOpenMPClause(CKind, WrongDirective);
3245 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
3246 CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)
3247 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3248 else
3249 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3250 break;
3251 case OMPC_threadset:
3252 case OMPC_fail:
3253 case OMPC_proc_bind:
3254 case OMPC_atomic_default_mem_order:
3255 case OMPC_at:
3256 case OMPC_severity:
3257 case OMPC_bind:
3258 // OpenMP [2.14.3.1, Restrictions]
3259 // Only a single default clause may be specified on a parallel, task or
3260 // teams directive.
3261 // OpenMP [2.5, parallel Construct, Restrictions]
3262 // At most one proc_bind clause can appear on the directive.
3263 // OpenMP [5.0, Requires directive, Restrictions]
3264 // At most one atomic_default_mem_order clause can appear
3265 // on the directive
3266 // OpenMP [5.1, error directive, Restrictions]
3267 // At most one at clause can appear on the directive
3268 // At most one severity clause can appear on the directive
3269 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3270 // At most one bind clause can appear on a loop directive.
3271 if (!FirstClause) {
3272 Diag(Tok, diag::err_omp_more_one_clause)
3273 << getOpenMPDirectiveName(DKind, OMPVersion)
3274 << getOpenMPClauseName(CKind) << 0;
3275 ErrorFound = true;
3276 }
3277
3278 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3279 break;
3280 case OMPC_device:
3281 case OMPC_schedule:
3282 case OMPC_dist_schedule:
3283 case OMPC_defaultmap:
3284 case OMPC_default:
3285 case OMPC_order:
3286 // OpenMP [2.7.1, Restrictions, p. 3]
3287 // Only one schedule clause can appear on a loop directive.
3288 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3289 // At most one defaultmap clause can appear on the directive.
3290 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3291 // At most one device clause can appear on the directive.
3292 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3293 // At most one order clause may appear on a construct.
3294 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3295 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3296 Diag(Tok, diag::err_omp_more_one_clause)
3297 << getOpenMPDirectiveName(DKind, OMPVersion)
3298 << getOpenMPClauseName(CKind) << 0;
3299 ErrorFound = true;
3300 }
3301 [[fallthrough]];
3302 case OMPC_if:
3303 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3304 break;
3305 case OMPC_holds:
3306 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3307 break;
3308 case OMPC_nowait:
3309 case OMPC_untied:
3310 case OMPC_mergeable:
3311 case OMPC_read:
3312 case OMPC_write:
3313 case OMPC_capture:
3314 case OMPC_compare:
3315 case OMPC_seq_cst:
3316 case OMPC_acq_rel:
3317 case OMPC_acquire:
3318 case OMPC_release:
3319 case OMPC_relaxed:
3320 case OMPC_weak:
3321 case OMPC_threads:
3322 case OMPC_simd:
3323 case OMPC_nogroup:
3324 case OMPC_unified_address:
3325 case OMPC_unified_shared_memory:
3326 case OMPC_reverse_offload:
3327 case OMPC_dynamic_allocators:
3328 case OMPC_full:
3329 // OpenMP [2.7.1, Restrictions, p. 9]
3330 // Only one ordered clause can appear on a loop directive.
3331 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3332 // Only one nowait clause can appear on a for directive.
3333 // OpenMP [5.0, Requires directive, Restrictions]
3334 // Each of the requires clauses can appear at most once on the directive.
3335 if (!FirstClause) {
3336 Diag(Tok, diag::err_omp_more_one_clause)
3337 << getOpenMPDirectiveName(DKind, OMPVersion)
3338 << getOpenMPClauseName(CKind) << 0;
3339 ErrorFound = true;
3340 }
3341
3342 if (CKind == OMPC_nowait && PP.LookAhead(/*N=*/0).is(tok::l_paren) &&
3343 getLangOpts().OpenMP >= 60)
3344 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3345 else
3346 Clause = ParseOpenMPClause(CKind, WrongDirective);
3347 break;
3348 case OMPC_self_maps:
3349 // OpenMP [6.0, self_maps clause]
3350 if (getLangOpts().OpenMP < 60) {
3351 Diag(Tok, diag::err_omp_expected_clause)
3352 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
3353 ErrorFound = true;
3354 }
3355 if (!FirstClause) {
3356 Diag(Tok, diag::err_omp_more_one_clause)
3357 << getOpenMPDirectiveName(DKind, OMPVersion)
3358 << getOpenMPClauseName(CKind) << 0;
3359 ErrorFound = true;
3360 }
3361 Clause = ParseOpenMPClause(CKind, WrongDirective);
3362 break;
3363 case OMPC_update:
3364 if (!FirstClause) {
3365 Diag(Tok, diag::err_omp_more_one_clause)
3366 << getOpenMPDirectiveName(DKind, OMPVersion)
3367 << getOpenMPClauseName(CKind) << 0;
3368 ErrorFound = true;
3369 }
3370
3371 Clause = (DKind == OMPD_depobj)
3372 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3373 : ParseOpenMPClause(CKind, WrongDirective);
3374 break;
3375 case OMPC_num_teams:
3376 case OMPC_thread_limit:
3377 if (!FirstClause) {
3378 Diag(Tok, diag::err_omp_more_one_clause)
3379 << getOpenMPDirectiveName(DKind, OMPVersion)
3380 << getOpenMPClauseName(CKind) << 0;
3381 ErrorFound = true;
3382 }
3383 [[fallthrough]];
3384 case OMPC_private:
3385 case OMPC_firstprivate:
3386 case OMPC_lastprivate:
3387 case OMPC_shared:
3388 case OMPC_reduction:
3389 case OMPC_task_reduction:
3390 case OMPC_in_reduction:
3391 case OMPC_linear:
3392 case OMPC_aligned:
3393 case OMPC_copyin:
3394 case OMPC_copyprivate:
3395 case OMPC_flush:
3396 case OMPC_depend:
3397 case OMPC_map:
3398 case OMPC_to:
3399 case OMPC_from:
3400 case OMPC_use_device_ptr:
3401 case OMPC_use_device_addr:
3402 case OMPC_is_device_ptr:
3403 case OMPC_has_device_addr:
3404 case OMPC_allocate:
3405 case OMPC_nontemporal:
3406 case OMPC_inclusive:
3407 case OMPC_exclusive:
3408 case OMPC_affinity:
3409 case OMPC_doacross:
3410 case OMPC_enter:
3411 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3412 CKind == OMPC_depend)
3413 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3414 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3415 break;
3416 case OMPC_sizes:
3417 if (!FirstClause) {
3418 Diag(Tok, diag::err_omp_more_one_clause)
3419 << getOpenMPDirectiveName(DKind, OMPVersion)
3420 << getOpenMPClauseName(CKind) << 0;
3421 ErrorFound = true;
3422 }
3423
3424 Clause = ParseOpenMPSizesClause();
3425 break;
3426 case OMPC_permutation:
3427 if (!FirstClause) {
3428 Diag(Tok, diag::err_omp_more_one_clause)
3429 << getOpenMPDirectiveName(DKind, OMPVersion)
3430 << getOpenMPClauseName(CKind) << 0;
3431 ErrorFound = true;
3432 }
3433 Clause = ParseOpenMPPermutationClause();
3434 break;
3435 case OMPC_uses_allocators:
3436 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3437 break;
3438 case OMPC_destroy:
3439 if (DKind != OMPD_interop) {
3440 if (!FirstClause) {
3441 Diag(Tok, diag::err_omp_more_one_clause)
3442 << getOpenMPDirectiveName(DKind, OMPVersion)
3443 << getOpenMPClauseName(CKind) << 0;
3444 ErrorFound = true;
3445 }
3446 Clause = ParseOpenMPClause(CKind, WrongDirective);
3447 break;
3448 }
3449 [[fallthrough]];
3450 case OMPC_init:
3451 case OMPC_use:
3452 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3453 break;
3454 case OMPC_device_type:
3455 case OMPC_unknown:
3456 skipUntilPragmaOpenMPEnd(DKind);
3457 break;
3458 case OMPC_threadprivate:
3459 case OMPC_groupprivate:
3460 case OMPC_uniform:
3461 case OMPC_match:
3462 if (!WrongDirective)
3463 Diag(Tok, diag::err_omp_unexpected_clause)
3464 << getOpenMPClauseName(CKind)
3465 << getOpenMPDirectiveName(DKind, OMPVersion);
3466 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3467 break;
3468 case OMPC_absent:
3469 case OMPC_contains: {
3470 SourceLocation Loc = ConsumeToken();
3471 SourceLocation LLoc = Tok.getLocation();
3472 SourceLocation RLoc;
3473 llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
3474 BalancedDelimiterTracker T(*this, tok::l_paren);
3475 T.consumeOpen();
3476 do {
3477 OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
3478 if (DK == OMPD_unknown) {
3479 skipUntilPragmaOpenMPEnd(OMPD_assume);
3480 Diag(Tok, diag::err_omp_unexpected_clause)
3481 << getOpenMPClauseName(CKind)
3482 << getOpenMPDirectiveName(DKind, OMPVersion);
3483 break;
3484 }
3486 DKVec.push_back(DK);
3487 ConsumeToken();
3488 } else {
3489 Diag(Tok, diag::err_omp_unexpected_clause)
3490 << getOpenMPClauseName(CKind)
3491 << getOpenMPDirectiveName(DKind, OMPVersion);
3492 }
3493 } while (TryConsumeToken(tok::comma));
3494 RLoc = Tok.getLocation();
3495 T.consumeClose();
3496 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3497 CKind, DKVec, Loc, LLoc, RLoc);
3498 break;
3499 }
3500 case OMPC_no_openmp:
3501 case OMPC_no_openmp_routines:
3502 case OMPC_no_openmp_constructs:
3503 case OMPC_no_parallelism: {
3504 if (!FirstClause) {
3505 Diag(Tok, diag::err_omp_more_one_clause)
3506 << getOpenMPDirectiveName(DKind, OMPVersion)
3507 << getOpenMPClauseName(CKind) << 0;
3508 ErrorFound = true;
3509 }
3510 SourceLocation Loc = ConsumeToken();
3511 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3512 CKind, Loc, Tok.getLocation());
3513 break;
3514 }
3515 case OMPC_ompx_attribute:
3516 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3517 break;
3518 case OMPC_ompx_bare:
3519 if (DKind == llvm::omp::Directive::OMPD_target) {
3520 // Flang splits the combined directives which requires OMPD_target to be
3521 // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
3522 // to explicitly check whether this clause is applied to an `omp target`
3523 // without `teams` and emit an error.
3524 Diag(Tok, diag::err_omp_unexpected_clause)
3525 << getOpenMPClauseName(CKind)
3526 << getOpenMPDirectiveName(DKind, OMPVersion);
3527 ErrorFound = true;
3528 WrongDirective = true;
3529 }
3530 if (WrongDirective)
3531 Diag(Tok, diag::note_ompx_bare_clause)
3532 << getOpenMPClauseName(CKind) << "target teams";
3533 if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3534 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3535 << getOpenMPClauseName(CKind)
3536 << getOpenMPDirectiveName(DKind, OMPVersion);
3537 ErrorFound = true;
3538 }
3539 Clause = ParseOpenMPClause(CKind, WrongDirective);
3540 break;
3541 case OMPC_looprange:
3542 Clause = ParseOpenMPLoopRangeClause();
3543 break;
3544 default:
3545 break;
3546 }
3547 return ErrorFound ? nullptr : Clause;
3548}
3549
3550/// Parses simple expression in parens for single-expression clauses of OpenMP
3551/// constructs.
3552/// \param RLoc Returned location of right paren.
3554 SourceLocation &RLoc,
3555 bool IsAddressOfOperand) {
3556 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3557 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3558 return ExprError();
3559
3560 SourceLocation ELoc = Tok.getLocation();
3561 ExprResult LHS(
3562 ParseCastExpression(CastParseKind::AnyCastExpr, IsAddressOfOperand,
3564 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3565 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3566
3567 // Parse ')'.
3568 RLoc = Tok.getLocation();
3569 if (!T.consumeClose())
3570 RLoc = T.getCloseLocation();
3571
3572 return Val;
3573}
3574
3575OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3576 bool ParseOnly) {
3578 SourceLocation LLoc = Tok.getLocation();
3579 SourceLocation RLoc;
3580
3581 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3582
3583 if (Val.isInvalid())
3584 return nullptr;
3585
3586 if (ParseOnly)
3587 return nullptr;
3588 return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3589 LLoc, RLoc);
3590}
3591
3592bool Parser::ParseOpenMPIndirectClause(
3593 SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3595 SourceLocation RLoc;
3596
3597 if (Tok.isNot(tok::l_paren)) {
3598 if (ParseOnly)
3599 return false;
3600 DTCI.Indirect = nullptr;
3601 return true;
3602 }
3603
3604 ExprResult Val =
3605 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3606 if (Val.isInvalid())
3607 return false;
3608
3609 if (ParseOnly)
3610 return false;
3611
3612 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3613 !Val.get()->isInstantiationDependent() &&
3615 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3616 if (Ret.isInvalid())
3617 return false;
3618 llvm::APSInt Result;
3619 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3621 if (Ret.isInvalid())
3622 return false;
3623 DTCI.Indirect = Val.get();
3624 return true;
3625 }
3626 return false;
3627}
3628
3629bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3630 OpenMPClauseKind Kind) {
3631 const Token &Tok = getCurToken();
3632 bool HasError = false;
3633 bool IsTarget = false;
3634 bool IsTargetSync = false;
3635
3636 while (Tok.is(tok::identifier)) {
3637 // Currently prefer_type is only allowed with 'init' and it must be first.
3638 bool PreferTypeAllowed = Kind == OMPC_init &&
3639 InteropInfo.PreferTypes.empty() && !IsTarget &&
3640 !IsTargetSync;
3641 if (Tok.getIdentifierInfo()->isStr("target")) {
3642 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3643 // Each interop-type may be specified on an action-clause at most
3644 // once.
3645 if (IsTarget)
3646 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3647 IsTarget = true;
3648 ConsumeToken();
3649 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3650 if (IsTargetSync)
3651 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3652 IsTargetSync = true;
3653 ConsumeToken();
3654 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3655 PreferTypeAllowed) {
3656 ConsumeToken();
3657 BalancedDelimiterTracker PT(*this, tok::l_paren,
3658 tok::annot_pragma_openmp_end);
3659 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3660 HasError = true;
3661
3662 while (Tok.isNot(tok::r_paren)) {
3663 SourceLocation Loc = Tok.getLocation();
3664 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
3665 ExprResult PTExpr = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3666 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3667 /*DiscardedValue=*/false);
3668 if (PTExpr.isUsable()) {
3669 InteropInfo.PreferTypes.push_back(PTExpr.get());
3670 } else {
3671 HasError = true;
3672 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3674 }
3675
3676 if (Tok.is(tok::comma))
3677 ConsumeToken();
3678 }
3679 PT.consumeClose();
3680 } else {
3681 HasError = true;
3682 Diag(Tok, diag::err_omp_expected_interop_type);
3683 ConsumeToken();
3684 }
3685 if (!Tok.is(tok::comma))
3686 break;
3687 ConsumeToken();
3688 }
3689
3690 if (!HasError && !IsTarget && !IsTargetSync) {
3691 Diag(Tok, diag::err_omp_expected_interop_type);
3692 HasError = true;
3693 }
3694
3695 if (Kind == OMPC_init) {
3696 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3697 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3698 if (Tok.is(tok::colon))
3699 ConsumeToken();
3700 }
3701
3702 // As of OpenMP 5.1,there are two interop-types, "target" and
3703 // "targetsync". Either or both are allowed for a single interop.
3704 InteropInfo.IsTarget = IsTarget;
3705 InteropInfo.IsTargetSync = IsTargetSync;
3706
3707 return HasError;
3708}
3709
3710OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3711 bool ParseOnly) {
3712 SourceLocation Loc = ConsumeToken();
3713 // Parse '('.
3714 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3715 if (T.expectAndConsume(diag::err_expected_lparen_after,
3716 getOpenMPClauseName(Kind).data()))
3717 return nullptr;
3718
3719 bool InteropError = false;
3720 OMPInteropInfo InteropInfo;
3721 if (Kind == OMPC_init)
3722 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3723
3724 // Parse the variable.
3725 SourceLocation VarLoc = Tok.getLocation();
3726 ExprResult InteropVarExpr = ParseAssignmentExpression();
3727 if (!InteropVarExpr.isUsable()) {
3728 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3730 }
3731
3732 // Parse ')'.
3733 SourceLocation RLoc = Tok.getLocation();
3734 if (!T.consumeClose())
3735 RLoc = T.getCloseLocation();
3736
3737 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3738 return nullptr;
3739
3740 if (Kind == OMPC_init)
3741 return Actions.OpenMP().ActOnOpenMPInitClause(
3742 InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3743 RLoc);
3744 if (Kind == OMPC_use)
3745 return Actions.OpenMP().ActOnOpenMPUseClause(
3746 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3747
3748 if (Kind == OMPC_destroy)
3749 return Actions.OpenMP().ActOnOpenMPDestroyClause(
3750 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3751
3752 llvm_unreachable("Unexpected interop variable clause.");
3753}
3754
3755OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3756 SourceLocation Loc = ConsumeToken();
3757 // Parse '('.
3758 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3759 if (T.expectAndConsume(diag::err_expected_lparen_after,
3760 getOpenMPClauseName(OMPC_ompx_attribute).data()))
3761 return nullptr;
3762
3763 ParsedAttributes ParsedAttrs(AttrFactory);
3764 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
3765
3766 // Parse ')'.
3767 if (T.consumeClose())
3768 return nullptr;
3769
3770 if (ParseOnly)
3771 return nullptr;
3772
3773 SmallVector<Attr *> Attrs;
3774 for (const ParsedAttr &PA : ParsedAttrs) {
3775 switch (PA.getKind()) {
3776 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3777 if (!PA.checkExactlyNumArgs(Actions, 2))
3778 continue;
3779 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
3780 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
3781 Attrs.push_back(A);
3782 continue;
3783 case ParsedAttr::AT_AMDGPUWavesPerEU:
3784 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3785 !PA.checkAtMostNumArgs(Actions, 2))
3786 continue;
3787 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
3788 PA, PA.getArgAsExpr(0),
3789 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
3790 Attrs.push_back(A);
3791 continue;
3792 case ParsedAttr::AT_CUDALaunchBounds:
3793 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3794 !PA.checkAtMostNumArgs(Actions, 2))
3795 continue;
3796 if (auto *A = Actions.CreateLaunchBoundsAttr(
3797 PA, PA.getArgAsExpr(0),
3798 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
3799 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
3800 Attrs.push_back(A);
3801 continue;
3802 default:
3803 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3804 continue;
3805 };
3806 }
3807
3808 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
3809 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
3810}
3811
3812OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
3813 bool ParseOnly) {
3814 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
3815 if (!Val || ParseOnly)
3816 return nullptr;
3817 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3818 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
3819 static_cast<DefaultKind>(Val->Type) ==
3820 OMP_DEFAULT_firstprivate)) {
3821 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3822 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
3823 OMP_DEFAULT_private
3824 ? OMPC_private
3825 : OMPC_firstprivate)
3826 << getOpenMPClauseName(OMPC_default) << "5.1";
3827 return nullptr;
3828 }
3829 return Actions.OpenMP().ActOnOpenMPSimpleClause(
3830 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
3831}
3832
3833OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
3834 SourceLocation Loc = Tok.getLocation();
3836
3837 if (ParseOnly)
3838 return nullptr;
3839 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
3840}
3841
3842OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
3843 OpenMPClauseKind Kind,
3844 bool ParseOnly) {
3845 SourceLocation Loc = ConsumeToken();
3846 SourceLocation DelimLoc;
3847 // Parse '('.
3848 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3849 if (T.expectAndConsume(diag::err_expected_lparen_after,
3850 getOpenMPClauseName(Kind).data()))
3851 return nullptr;
3852
3853 ExprResult Val;
3854 SmallVector<unsigned, 4> Arg;
3855 SmallVector<SourceLocation, 4> KLoc;
3856 if (Kind == OMPC_schedule) {
3857 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3858 Arg.resize(NumberOfElements);
3859 KLoc.resize(NumberOfElements);
3860 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
3861 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
3862 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
3863 unsigned KindModifier = getOpenMPSimpleClauseType(
3864 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3865 if (KindModifier > OMPC_SCHEDULE_unknown) {
3866 // Parse 'modifier'
3867 Arg[Modifier1] = KindModifier;
3868 KLoc[Modifier1] = Tok.getLocation();
3869 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3870 Tok.isNot(tok::annot_pragma_openmp_end))
3872 if (Tok.is(tok::comma)) {
3873 // Parse ',' 'modifier'
3875 KindModifier = getOpenMPSimpleClauseType(
3876 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3877 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
3878 ? KindModifier
3879 : (unsigned)OMPC_SCHEDULE_unknown;
3880 KLoc[Modifier2] = Tok.getLocation();
3881 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3882 Tok.isNot(tok::annot_pragma_openmp_end))
3884 }
3885 // Parse ':'
3886 if (Tok.is(tok::colon))
3888 else
3889 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
3890 KindModifier = getOpenMPSimpleClauseType(
3891 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3892 }
3893 Arg[ScheduleKind] = KindModifier;
3894 KLoc[ScheduleKind] = Tok.getLocation();
3895 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3896 Tok.isNot(tok::annot_pragma_openmp_end))
3898 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3899 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3900 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3901 Tok.is(tok::comma))
3902 DelimLoc = ConsumeAnyToken();
3903 } else if (Kind == OMPC_dist_schedule) {
3904 Arg.push_back(getOpenMPSimpleClauseType(
3905 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3906 KLoc.push_back(Tok.getLocation());
3907 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3908 Tok.isNot(tok::annot_pragma_openmp_end))
3910 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
3911 DelimLoc = ConsumeAnyToken();
3912 } else if (Kind == OMPC_default) {
3913 // Get a default modifier
3914 unsigned Modifier = getOpenMPSimpleClauseType(
3915 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3916
3917 Arg.push_back(Modifier);
3918 KLoc.push_back(Tok.getLocation());
3919 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3920 Tok.isNot(tok::annot_pragma_openmp_end))
3922 // Parse ':'
3923 if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {
3925 // Get a variable-category attribute for default clause modifier
3926 OpenMPDefaultClauseVariableCategory VariableCategory =
3928 Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3929 Arg.push_back(VariableCategory);
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 } else {
3935 Arg.push_back(OMPC_DEFAULT_VC_all);
3936 KLoc.push_back(SourceLocation());
3937 }
3938 } else if (Kind == OMPC_defaultmap) {
3939 // Get a defaultmap modifier
3940 unsigned Modifier = getOpenMPSimpleClauseType(
3941 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3942
3943 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3944 // pointer
3945 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
3947 Arg.push_back(Modifier);
3948 KLoc.push_back(Tok.getLocation());
3949 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3950 Tok.isNot(tok::annot_pragma_openmp_end))
3952 // Parse ':'
3953 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
3954 if (Tok.is(tok::colon))
3956 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
3957 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
3958 // Get a defaultmap kind
3959 Arg.push_back(getOpenMPSimpleClauseType(
3960 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3961 KLoc.push_back(Tok.getLocation());
3962 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3963 Tok.isNot(tok::annot_pragma_openmp_end))
3965 } else {
3966 Arg.push_back(OMPC_DEFAULTMAP_unknown);
3967 KLoc.push_back(SourceLocation());
3968 }
3969 } else if (Kind == OMPC_order) {
3970 enum { Modifier, OrderKind, NumberOfElements };
3971 Arg.resize(NumberOfElements);
3972 KLoc.resize(NumberOfElements);
3973 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
3974 Arg[OrderKind] = OMPC_ORDER_unknown;
3975 unsigned KindModifier = getOpenMPSimpleClauseType(
3976 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3977 if (KindModifier > OMPC_ORDER_unknown) {
3978 // Parse 'modifier'
3979 Arg[Modifier] = KindModifier;
3980 KLoc[Modifier] = Tok.getLocation();
3981 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3982 Tok.isNot(tok::annot_pragma_openmp_end))
3984 // Parse ':'
3985 if (Tok.is(tok::colon))
3987 else
3988 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
3989 KindModifier = getOpenMPSimpleClauseType(
3990 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3991 }
3992 Arg[OrderKind] = KindModifier;
3993 KLoc[OrderKind] = Tok.getLocation();
3994 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3995 Tok.isNot(tok::annot_pragma_openmp_end))
3997 } else if (Kind == OMPC_device) {
3998 // Only target executable directives support extended device construct.
3999 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4000 NextToken().is(tok::colon)) {
4001 // Parse optional <device modifier> ':'
4002 Arg.push_back(getOpenMPSimpleClauseType(
4003 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4004 KLoc.push_back(Tok.getLocation());
4006 // Parse ':'
4008 } else {
4009 Arg.push_back(OMPC_DEVICE_unknown);
4010 KLoc.emplace_back();
4011 }
4012 } else if (Kind == OMPC_grainsize) {
4013 // Parse optional <grainsize modifier> ':'
4016 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4017 getLangOpts()));
4018 if (getLangOpts().OpenMP >= 51) {
4019 if (NextToken().is(tok::colon)) {
4020 Arg.push_back(Modifier);
4021 KLoc.push_back(Tok.getLocation());
4022 // Parse modifier
4024 // Parse ':'
4026 } else {
4027 if (Modifier == OMPC_GRAINSIZE_strict) {
4028 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4029 // Parse modifier
4031 }
4032 Arg.push_back(OMPC_GRAINSIZE_unknown);
4033 KLoc.emplace_back();
4034 }
4035 } else {
4036 Arg.push_back(OMPC_GRAINSIZE_unknown);
4037 KLoc.emplace_back();
4038 }
4039 } else if (Kind == OMPC_dyn_groupprivate) {
4040 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
4041 Arg.resize(NumberOfModifiers);
4042 KLoc.resize(NumberOfModifiers);
4043 Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
4044 Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
4045
4046 auto ConsumeModifier = [&]() {
4047 unsigned Type = NumberOfModifiers;
4048 unsigned Modifier;
4049 SourceLocation Loc;
4050 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
4051 NextToken().is(tok::l_paren)) {
4052 ConsumeToken();
4053 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4054 ParenT.consumeOpen();
4055
4056 Modifier = getOpenMPSimpleClauseType(
4057 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4060 Diag(Tok.getLocation(), diag::err_expected)
4061 << "'abort', 'null' or 'default_mem' in fallback modifier";
4062 SkipUntil(tok::r_paren);
4063 return std::make_tuple(Type, Modifier, Loc);
4064 }
4065 Type = ComplexModifier;
4066 Loc = Tok.getLocation();
4067 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4068 Tok.isNot(tok::annot_pragma_openmp_end))
4070 ParenT.consumeClose();
4071 } else {
4072 Modifier = getOpenMPSimpleClauseType(
4073 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4074 if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
4075 Type = SimpleModifier;
4076 Loc = Tok.getLocation();
4077 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4078 Tok.isNot(tok::annot_pragma_openmp_end))
4080 }
4081 }
4082 return std::make_tuple(Type, Modifier, Loc);
4083 };
4084
4085 auto SaveModifier = [&](unsigned Type, unsigned Modifier,
4086 SourceLocation Loc) {
4087 assert(Type < NumberOfModifiers && "Unexpected modifier type");
4088 if (!KLoc[Type].isValid()) {
4089 Arg[Type] = Modifier;
4090 KLoc[Type] = Loc;
4091 } else {
4092 Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
4093 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
4094 << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
4095 }
4096 };
4097
4098 // Parse 'modifier'
4099 auto [Type1, Mod1, Loc1] = ConsumeModifier();
4100 if (Type1 < NumberOfModifiers) {
4101 SaveModifier(Type1, Mod1, Loc1);
4102 if (Tok.is(tok::comma)) {
4103 // Parse ',' 'modifier'
4105 auto [Type2, Mod2, Loc2] = ConsumeModifier();
4106 if (Type2 < NumberOfModifiers)
4107 SaveModifier(Type2, Mod2, Loc2);
4108 }
4109 // Parse ':'
4110 if (Tok.is(tok::colon))
4112 else
4113 Diag(Tok, diag::warn_pragma_expected_colon)
4114 << "dyn_groupprivate modifier";
4115 }
4116 } else if (Kind == OMPC_num_tasks) {
4117 // Parse optional <num_tasks modifier> ':'
4120 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4121 getLangOpts()));
4122 if (getLangOpts().OpenMP >= 51) {
4123 if (NextToken().is(tok::colon)) {
4124 Arg.push_back(Modifier);
4125 KLoc.push_back(Tok.getLocation());
4126 // Parse modifier
4128 // Parse ':'
4130 } else {
4131 if (Modifier == OMPC_NUMTASKS_strict) {
4132 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4133 // Parse modifier
4135 }
4136 Arg.push_back(OMPC_NUMTASKS_unknown);
4137 KLoc.emplace_back();
4138 }
4139 } else {
4140 Arg.push_back(OMPC_NUMTASKS_unknown);
4141 KLoc.emplace_back();
4142 }
4143 } else if (Kind == OMPC_num_threads) {
4144 // Parse optional <num_threads modifier> ':'
4147 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4148 getLangOpts()));
4149 if (getLangOpts().OpenMP >= 60) {
4150 if (NextToken().is(tok::colon)) {
4151 Arg.push_back(Modifier);
4152 KLoc.push_back(Tok.getLocation());
4153 // Parse modifier
4155 // Parse ':'
4157 } else {
4158 if (Modifier == OMPC_NUMTHREADS_strict) {
4159 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4160 // Parse modifier
4162 }
4163 Arg.push_back(OMPC_NUMTHREADS_unknown);
4164 KLoc.emplace_back();
4165 }
4166 } else {
4167 Arg.push_back(OMPC_NUMTHREADS_unknown);
4168 KLoc.emplace_back();
4169 }
4170 } else {
4171 assert(Kind == OMPC_if);
4172 KLoc.push_back(Tok.getLocation());
4173 TentativeParsingAction TPA(*this);
4174 auto DK = parseOpenMPDirectiveKind(*this);
4175 Arg.push_back(static_cast<unsigned>(DK));
4176 if (DK != OMPD_unknown) {
4177 ConsumeToken();
4178 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4179 TPA.Commit();
4180 DelimLoc = ConsumeToken();
4181 } else {
4182 TPA.Revert();
4183 Arg.back() = unsigned(OMPD_unknown);
4184 }
4185 } else {
4186 TPA.Revert();
4187 }
4188 }
4189
4190 bool NeedAnExpression =
4191 (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4192 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||
4193 Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
4194 Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;
4195 if (NeedAnExpression) {
4196 SourceLocation ELoc = Tok.getLocation();
4197 ExprResult LHS(
4198 ParseCastExpression(CastParseKind::AnyCastExpr, false,
4200 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4201 Val =
4202 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4203 }
4204
4205 // Parse ')'.
4206 SourceLocation RLoc = Tok.getLocation();
4207 if (!T.consumeClose())
4208 RLoc = T.getCloseLocation();
4209
4210 if (NeedAnExpression && Val.isInvalid())
4211 return nullptr;
4212
4213 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
4214 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
4215 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
4216 Diag(KLoc[0], diag::err_omp_invalid_dsa)
4217 << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==
4218 OMP_DEFAULT_private
4219 ? OMPC_private
4220 : OMPC_firstprivate)
4221 << getOpenMPClauseName(OMPC_default) << "5.1";
4222 return nullptr;
4223 }
4224
4225 if (ParseOnly)
4226 return nullptr;
4227 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4228 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4229}
4230
4231static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4232 UnqualifiedId &ReductionId) {
4233 if (ReductionIdScopeSpec.isEmpty()) {
4234 auto OOK = OO_None;
4235 switch (P.getCurToken().getKind()) {
4236 case tok::plus:
4237 OOK = OO_Plus;
4238 break;
4239 case tok::minus:
4240 OOK = OO_Minus;
4241 break;
4242 case tok::star:
4243 OOK = OO_Star;
4244 break;
4245 case tok::amp:
4246 OOK = OO_Amp;
4247 break;
4248 case tok::pipe:
4249 OOK = OO_Pipe;
4250 break;
4251 case tok::caret:
4252 OOK = OO_Caret;
4253 break;
4254 case tok::ampamp:
4255 OOK = OO_AmpAmp;
4256 break;
4257 case tok::pipepipe:
4258 OOK = OO_PipePipe;
4259 break;
4260 default:
4261 break;
4262 }
4263 if (OOK != OO_None) {
4264 SourceLocation OpLoc = P.ConsumeToken();
4265 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4266 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4267 return false;
4268 }
4269 }
4270 return P.ParseUnqualifiedId(
4271 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4272 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4273 /*AllowDestructorName*/ false,
4274 /*AllowConstructorName*/ false,
4275 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4276}
4277
4278/// Checks if the token is a valid map-type-modifier.
4279/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4281 Token Tok = P.getCurToken();
4282 if (!Tok.is(tok::identifier))
4284
4285 Preprocessor &PP = P.getPreprocessor();
4286 OpenMPMapModifierKind TypeModifier =
4288 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4289 return TypeModifier;
4290}
4291
4293 // Parse '('.
4294 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4295 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4296 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4298 return true;
4299 }
4300 // Parse mapper-identifier
4301 if (getLangOpts().CPlusPlus)
4302 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4303 /*ObjectType=*/nullptr,
4304 /*ObjectHasErrors=*/false,
4305 /*EnteringContext=*/false);
4306 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4307 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4308 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4310 return true;
4311 }
4312 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4313 Data.ReductionOrMapperId = DeclarationNameInfo(
4314 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4315 ConsumeToken();
4316 // Parse ')'.
4317 return T.consumeClose();
4318}
4319
4321
4323 bool HasMapType = false;
4324 SourceLocation PreMapLoc = Tok.getLocation();
4325 StringRef PreMapName = "";
4326 while (getCurToken().isNot(tok::colon)) {
4327 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4328 OpenMPMapClauseKind MapKind = isMapType(*this);
4329 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4330 TypeModifier == OMPC_MAP_MODIFIER_close ||
4331 TypeModifier == OMPC_MAP_MODIFIER_present ||
4332 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4333 Data.MapTypeModifiers.push_back(TypeModifier);
4334 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4335 if (PP.LookAhead(0).isNot(tok::comma) &&
4336 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4337 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4338 << "map type modifier";
4339 ConsumeToken();
4340 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4341 Data.MapTypeModifiers.push_back(TypeModifier);
4342 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4343 ConsumeToken();
4345 return true;
4346 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4347 getLangOpts().OpenMP >= 52)
4348 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4349 << "map type modifier";
4350
4351 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4352 if (!HasMapType) {
4353 HasMapType = true;
4354 Data.ExtraModifier = MapKind;
4355 MapKind = OMPC_MAP_unknown;
4356 PreMapLoc = Tok.getLocation();
4357 PreMapName = Tok.getIdentifierInfo()->getName();
4358 } else {
4359 Diag(Tok, diag::err_omp_more_one_map_type);
4360 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4361 << PreMapName;
4362 }
4363 ConsumeToken();
4364 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
4365 Data.MapTypeModifiers.push_back(TypeModifier);
4366 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4367 if (PP.LookAhead(0).isNot(tok::comma) &&
4368 PP.LookAhead(0).isNot(tok::colon))
4369 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4370 << "map type modifier";
4371 if (getLangOpts().OpenMP < 60)
4372 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4373 << (getLangOpts().OpenMP >= 51
4374 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4375 : 0)
4376 << getLangOpts().OpenMPExtensions << 0;
4377 ConsumeToken();
4378 } else {
4379 // For the case of unknown map-type-modifier or a map-type.
4380 // Map-type is followed by a colon; the function returns when it
4381 // encounters a token followed by a colon.
4382 if (Tok.is(tok::comma)) {
4383 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4384 ConsumeToken();
4385 continue;
4386 }
4387 // Potential map-type token as it is followed by a colon.
4388 if (PP.LookAhead(0).is(tok::colon)) {
4389 if (getLangOpts().OpenMP >= 60) {
4390 break;
4391 } else {
4392 return false;
4393 }
4394 }
4395
4396 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4397 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4398 : 0)
4399 << getLangOpts().OpenMPExtensions
4400 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
4401 ConsumeToken();
4402 }
4403 if (getCurToken().is(tok::comma))
4404 ConsumeToken();
4405 }
4406 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4407 if (!Tok.is(tok::colon)) {
4408 Diag(Tok, diag::err_omp_unknown_map_type);
4409 ConsumeToken();
4410 } else {
4411 Data.ExtraModifier = OMPC_MAP_unknown;
4412 }
4413 }
4414 return false;
4415}
4416
4417/// Checks if the token is a valid map-type.
4418/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4420 Token Tok = P.getCurToken();
4421 // The map-type token can be either an identifier or the C++ delete keyword.
4422 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4423 return OMPC_MAP_unknown;
4424 Preprocessor &PP = P.getPreprocessor();
4425 unsigned MapType =
4427 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4428 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4429 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4430 return static_cast<OpenMPMapClauseKind>(MapType);
4431 return OMPC_MAP_unknown;
4432}
4433
4434/// Parse map-type in map clause.
4435/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4436/// where, map-type ::= to | from | tofrom | alloc | release | delete
4438 Token Tok = P.getCurToken();
4439 if (Tok.is(tok::colon)) {
4440 P.Diag(Tok, diag::err_omp_map_type_missing);
4441 return;
4442 }
4443 Data.ExtraModifier = isMapType(P);
4444 if (Data.ExtraModifier == OMPC_MAP_unknown)
4445 P.Diag(Tok, diag::err_omp_unknown_map_type);
4446 P.ConsumeToken();
4447}
4448
4449ExprResult Parser::ParseOpenMPIteratorsExpr() {
4450 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4451 "Expected 'iterator' token.");
4452 SourceLocation IteratorKwLoc = ConsumeToken();
4453
4454 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4455 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4456 return ExprError();
4457
4458 SourceLocation LLoc = T.getOpenLocation();
4459 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4460 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4461 // Check if the type parsing is required.
4462 ParsedType IteratorType;
4463 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4464 // identifier '=' is not found - parse type.
4466 if (TR.isInvalid()) {
4467 T.skipToEnd();
4468 return ExprError();
4469 }
4470 IteratorType = TR.get();
4471 }
4472
4473 // Parse identifier.
4474 IdentifierInfo *II = nullptr;
4475 SourceLocation IdLoc;
4476 if (Tok.is(tok::identifier)) {
4477 II = Tok.getIdentifierInfo();
4478 IdLoc = ConsumeToken();
4479 } else {
4480 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4481 }
4482
4483 // Parse '='.
4484 SourceLocation AssignLoc;
4485 if (Tok.is(tok::equal))
4486 AssignLoc = ConsumeToken();
4487 else
4488 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4489
4490 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4491 ColonProtectionRAIIObject ColonRAII(*this);
4492 // Parse <begin>
4493 SourceLocation Loc = Tok.getLocation();
4494 ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4495 ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4496 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4497 /*DiscardedValue=*/false);
4498 // Parse ':'.
4499 SourceLocation ColonLoc;
4500 if (Tok.is(tok::colon))
4501 ColonLoc = ConsumeToken();
4502
4503 // Parse <end>
4504 Loc = Tok.getLocation();
4505 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4506 ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4507 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4508 /*DiscardedValue=*/false);
4509
4510 SourceLocation SecColonLoc;
4511 ExprResult Step;
4512 // Parse optional step.
4513 if (Tok.is(tok::colon)) {
4514 // Parse ':'
4515 SecColonLoc = ConsumeToken();
4516 // Parse <step>
4517 Loc = Tok.getLocation();
4518 LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
4519 Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4520 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4521 /*DiscardedValue=*/false);
4522 }
4523
4524 // Parse ',' or ')'
4525 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4526 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4527 if (Tok.is(tok::comma))
4528 ConsumeToken();
4529
4530 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4531 D.DeclIdent = II;
4532 D.DeclIdentLoc = IdLoc;
4533 D.Type = IteratorType;
4534 D.AssignLoc = AssignLoc;
4535 D.ColonLoc = ColonLoc;
4536 D.SecColonLoc = SecColonLoc;
4537 D.Range.Begin = Begin.get();
4538 D.Range.End = End.get();
4539 D.Range.Step = Step.get();
4540 }
4541
4542 // Parse ')'.
4543 SourceLocation RLoc = Tok.getLocation();
4544 if (!T.consumeClose())
4545 RLoc = T.getCloseLocation();
4546
4547 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4548 LLoc, RLoc, Data);
4549}
4550
4553 const LangOptions &LangOpts) {
4554 // Currently the only reserved locator is 'omp_all_memory' which is only
4555 // allowed on a depend clause.
4556 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4557 return false;
4558
4559 if (Tok.is(tok::identifier) &&
4560 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4561
4562 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4563 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4564 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4565 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4566 Data.ExtraModifier != OMPC_DEPEND_inout)
4567 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4568 else
4569 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4570 ? OMPC_DEPEND_outallmemory
4571 : OMPC_DEPEND_inoutallmemory;
4572 ConsumeToken();
4573 return true;
4574 }
4575 return false;
4576}
4577
4578/// Parse step size expression. Returns true if parsing is successfull,
4579/// otherwise returns false.
4581 OpenMPClauseKind CKind, SourceLocation ELoc) {
4583 Sema &Actions = P.getActions();
4584 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4585 /*DiscardedValue*/ false);
4586 if (Tail.isUsable()) {
4587 Data.DepModOrTailExpr = Tail.get();
4588 Token CurTok = P.getCurToken();
4589 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4590 P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4591 }
4592 return true;
4593 }
4594 return false;
4595}
4596
4597/// Parse 'allocate' clause modifiers.
4598/// If allocator-modifier exists, return an expression for it. For both
4599/// allocator and align modifiers, set Data fields as appropriate.
4600static ExprResult
4603 const Token &Tok = P.getCurToken();
4604 Preprocessor &PP = P.getPreprocessor();
4605 ExprResult Tail;
4606 ExprResult Val;
4607 SourceLocation RLoc;
4608 bool AllocatorSeen = false;
4609 bool AlignSeen = false;
4610 SourceLocation CurrentModifierLoc = Tok.getLocation();
4611 auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4613
4614 // Modifiers did not exist before 5.1
4615 if (P.getLangOpts().OpenMP < 51)
4616 return P.ParseAssignmentExpression();
4617
4618 // An allocator-simple-modifier is exclusive and must appear alone. See
4619 // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
4620 // description of "exclusive" property. If we don't recognized an explicit
4621 // simple-/complex- modifier, assume we're looking at expression
4622 // representing allocator and consider ourselves done.
4623 if (CurrentModifier == OMPC_ALLOCATE_unknown)
4624 return P.ParseAssignmentExpression();
4625
4626 do {
4627 P.ConsumeToken();
4628 if (Tok.is(tok::l_paren)) {
4629 switch (CurrentModifier) {
4630 case OMPC_ALLOCATE_allocator: {
4631 if (AllocatorSeen) {
4632 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4633 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4634 << getOpenMPClauseName(Kind);
4635 } else {
4636 Data.AllocClauseModifiers.push_back(CurrentModifier);
4637 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4638 }
4639 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
4640 tok::annot_pragma_openmp_end);
4641 AllocateT.consumeOpen();
4642 Tail = P.ParseAssignmentExpression();
4643 AllocateT.consumeClose();
4644 AllocatorSeen = true;
4645 break;
4646 }
4647 case OMPC_ALLOCATE_align: {
4648 if (AlignSeen) {
4649 P.Diag(Tok, diag::err_omp_duplicate_modifier)
4650 << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
4651 << getOpenMPClauseName(Kind);
4652 } else {
4653 Data.AllocClauseModifiers.push_back(CurrentModifier);
4654 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
4655 }
4656 Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
4657 if (Val.isUsable())
4658 Data.AllocateAlignment = Val.get();
4659 AlignSeen = true;
4660 break;
4661 }
4662 default:
4663 llvm_unreachable("Unexpected allocate modifier");
4664 }
4665 } else {
4666 P.Diag(Tok, diag::err_expected) << tok::l_paren;
4667 }
4668 if (Tok.isNot(tok::comma))
4669 break;
4670 P.ConsumeToken();
4671 CurrentModifierLoc = Tok.getLocation();
4672 CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4674 // A modifier followed by a comma implies another modifier.
4675 if (CurrentModifier == OMPC_ALLOCATE_unknown) {
4676 P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
4677 break;
4678 }
4679 } while (!AllocatorSeen || !AlignSeen);
4680 return Tail;
4681}
4682
4684 OpenMPClauseKind Kind,
4687 UnqualifiedId UnqualifiedReductionId;
4688 bool InvalidReductionId = false;
4689 bool IsInvalidMapperModifier = false;
4690
4691 // Parse '('.
4692 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4693 if (T.expectAndConsume(diag::err_expected_lparen_after,
4694 getOpenMPClauseName(Kind).data()))
4695 return true;
4696
4697 bool HasIterator = false;
4698 bool InvalidIterator = false;
4699 bool NeedRParenForLinear = false;
4700 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4701 tok::annot_pragma_openmp_end);
4702 // Handle reduction-identifier for reduction clause.
4703 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4704 Kind == OMPC_in_reduction) {
4705 Data.ExtraModifier = OMPC_REDUCTION_unknown;
4706 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4707 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4708 NextToken().is(tok::comma)) {
4709 // Parse optional reduction modifier.
4710 Data.ExtraModifier =
4711 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4712 Data.ExtraModifierLoc = Tok.getLocation();
4713 ConsumeToken();
4714 assert(Tok.is(tok::comma) && "Expected comma.");
4715 (void)ConsumeToken();
4716 }
4717 // Handle original(private / shared) Modifier
4718 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
4719 Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
4720 NextToken().is(tok::l_paren)) {
4721 // Parse original(private) modifier.
4722 ConsumeToken();
4723 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4724 ParenT.consumeOpen();
4725 if (Tok.is(tok::kw_private)) {
4726 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
4727 Data.OriginalSharingModifierLoc = Tok.getLocation();
4728 ConsumeToken();
4729 } else if (Tok.is(tok::identifier) &&
4730 (PP.getSpelling(Tok) == "shared" ||
4731 PP.getSpelling(Tok) == "default")) {
4732 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
4733 Data.OriginalSharingModifierLoc = Tok.getLocation();
4734 ConsumeToken();
4735 } else {
4736 Diag(Tok.getLocation(), diag::err_expected)
4737 << "'private or shared or default'";
4738 SkipUntil(tok::r_paren);
4739 return false;
4740 }
4741 ParenT.consumeClose();
4742 if (!Tok.is(tok::comma)) {
4743 Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
4744 return false;
4745 }
4746 (void)ConsumeToken();
4747 }
4748 ColonProtectionRAIIObject ColonRAII(*this);
4749 if (getLangOpts().CPlusPlus)
4750 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4751 /*ObjectType=*/nullptr,
4752 /*ObjectHasErrors=*/false,
4753 /*EnteringContext=*/false);
4754 InvalidReductionId = ParseReductionId(
4755 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4756 if (InvalidReductionId) {
4757 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4759 }
4760 if (Tok.is(tok::colon))
4761 Data.ColonLoc = ConsumeToken();
4762 else
4763 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4764 if (!InvalidReductionId)
4765 Data.ReductionOrMapperId =
4766 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4767 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4768 if (getLangOpts().OpenMP >= 50) {
4769 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4770 // Handle optional dependence modifier.
4771 // iterator(iterators-definition)
4772 // where iterators-definition is iterator-specifier [,
4773 // iterators-definition ]
4774 // where iterator-specifier is [ iterator-type ] identifier =
4775 // range-specification
4776 HasIterator = true;
4778 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4779 Data.DepModOrTailExpr = IteratorRes.get();
4780 // Parse ','
4781 ExpectAndConsume(tok::comma);
4782 }
4783 }
4784 // Handle dependency type for depend clause.
4785 ColonProtectionRAIIObject ColonRAII(*this);
4786 Data.ExtraModifier = getOpenMPSimpleClauseType(
4787 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4788 getLangOpts());
4789 Data.ExtraModifierLoc = Tok.getLocation();
4790 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
4791 (Kind == OMPC_doacross &&
4792 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
4793 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4795 } else {
4796 ConsumeToken();
4797 // Special processing for depend(source) clause.
4798 if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4799 Data.ExtraModifier == OMPC_DEPEND_source) {
4800 // Parse ')'.
4801 T.consumeClose();
4802 return false;
4803 }
4804 }
4805 if (Tok.is(tok::colon)) {
4806 Data.ColonLoc = ConsumeToken();
4807 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
4808 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4809 : diag::warn_pragma_expected_colon)
4810 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
4811 }
4812 if (Kind == OMPC_doacross) {
4813 if (Tok.is(tok::identifier) &&
4814 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
4815 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
4816 ? OMPC_DOACROSS_source_omp_cur_iteration
4817 : OMPC_DOACROSS_sink_omp_cur_iteration;
4818 ConsumeToken();
4819 }
4820 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4821 if (Tok.isNot(tok::minus)) {
4822 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4823 << getOpenMPClauseName(Kind) << 0 << 0;
4824 SkipUntil(tok::r_paren);
4825 return false;
4826 } else {
4827 ConsumeToken();
4828 SourceLocation Loc = Tok.getLocation();
4829 uint64_t Value = 0;
4830 if (Tok.isNot(tok::numeric_constant) ||
4831 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
4832 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
4833 << getOpenMPClauseName(Kind) << 0 << 0;
4834 SkipUntil(tok::r_paren);
4835 return false;
4836 }
4837 }
4838 }
4839 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4840 if (Tok.isNot(tok::r_paren)) {
4841 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4842 << getOpenMPClauseName(Kind) << 1 << 1;
4843 SkipUntil(tok::r_paren);
4844 return false;
4845 }
4846 }
4847 // Only the 'sink' case has the expression list.
4848 if (Kind == OMPC_doacross &&
4849 (Data.ExtraModifier == OMPC_DOACROSS_source ||
4850 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4851 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4852 // Parse ')'.
4853 T.consumeClose();
4854 return false;
4855 }
4856 }
4857 } else if (Kind == OMPC_linear) {
4858 // Try to parse modifier if any.
4859 Data.ExtraModifier = OMPC_LINEAR_val;
4860 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
4861 Data.ExtraModifier =
4862 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4863 Data.ExtraModifierLoc = ConsumeToken();
4864 LinearT.consumeOpen();
4865 NeedRParenForLinear = true;
4866 if (getLangOpts().OpenMP >= 52)
4867 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
4868 << "linear-modifier(list)" << getOpenMPClauseName(Kind)
4869 << "linear(list: [linear-modifier,] step(step-size))";
4870 }
4871 } else if (Kind == OMPC_lastprivate) {
4872 // Try to parse modifier if any.
4873 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
4874 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4875 // distribute and taskloop based directives.
4876 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
4877 !isOpenMPTaskLoopDirective(DKind)) &&
4878 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
4879 Data.ExtraModifier =
4880 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4881 Data.ExtraModifierLoc = Tok.getLocation();
4882 ConsumeToken();
4883 assert(Tok.is(tok::colon) && "Expected colon.");
4884 Data.ColonLoc = ConsumeToken();
4885 }
4886 } else if (Kind == OMPC_map) {
4887 // Handle optional iterator map modifier.
4888 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4889 HasIterator = true;
4891 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4892 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4893 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4894 Data.IteratorExpr = IteratorRes.get();
4895 // Parse ','
4896 ExpectAndConsume(tok::comma);
4897 if (getLangOpts().OpenMP < 52) {
4898 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4899 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
4900 << getLangOpts().OpenMPExtensions << 0;
4901 InvalidIterator = true;
4902 }
4903 }
4904 // Handle map type for map clause.
4905 ColonProtectionRAIIObject ColonRAII(*this);
4906
4907 // The first identifier may be a list item, a map-type or a
4908 // map-type-modifier. The map-type can also be delete which has the same
4909 // spelling of the C++ delete keyword.
4910 Data.ExtraModifier = OMPC_MAP_unknown;
4911 Data.ExtraModifierLoc = Tok.getLocation();
4912
4913 // Check for presence of a colon in the map clause.
4914 TentativeParsingAction TPA(*this);
4915 bool ColonPresent = false;
4916 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4917 StopBeforeMatch)) {
4918 if (Tok.is(tok::colon))
4919 ColonPresent = true;
4920 }
4921 TPA.Revert();
4922 // Only parse map-type-modifier[s] and map-type if a colon is present in
4923 // the map clause.
4924 if (ColonPresent) {
4925 if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
4926 Diag(Tok, diag::err_omp_map_modifier_specification_list);
4927 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
4928 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
4929 parseMapType(*this, Data);
4930 else
4931 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
4932 }
4933 if (Data.ExtraModifier == OMPC_MAP_unknown) {
4934 Data.ExtraModifier = OMPC_MAP_tofrom;
4935 if (getLangOpts().OpenMP >= 52) {
4936 if (DKind == OMPD_target_enter_data)
4937 Data.ExtraModifier = OMPC_MAP_to;
4938 else if (DKind == OMPD_target_exit_data)
4939 Data.ExtraModifier = OMPC_MAP_from;
4940 }
4941 Data.IsMapTypeImplicit = true;
4942 }
4943
4944 if (Tok.is(tok::colon))
4945 Data.ColonLoc = ConsumeToken();
4946 } else if (Kind == OMPC_to || Kind == OMPC_from) {
4947 while (Tok.is(tok::identifier)) {
4948 auto Modifier = static_cast<OpenMPMotionModifierKind>(
4949 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
4950 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
4951 break;
4952 Data.MotionModifiers.push_back(Modifier);
4953 Data.MotionModifiersLoc.push_back(Tok.getLocation());
4954 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
4955 ExprResult Tail;
4956 Tail = ParseOpenMPIteratorsExpr();
4957 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
4958 /*DiscardedValue=*/false);
4959 if (Tail.isUsable())
4960 Data.IteratorExpr = Tail.get();
4961 } else {
4962 ConsumeToken();
4963 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4964 IsInvalidMapperModifier = parseMapperModifier(Data);
4965 if (IsInvalidMapperModifier)
4966 break;
4967 }
4968 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
4969 if (getLangOpts().OpenMP < 51)
4970 break;
4971 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
4972 // TODO: Is that intentional?
4973 if (Tok.is(tok::comma))
4974 ConsumeToken();
4975 }
4976 }
4977 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
4978 if (!IsInvalidMapperModifier) {
4979 if (getLangOpts().OpenMP < 51)
4980 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
4981 else
4982 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
4983 }
4984 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4986 }
4987 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
4988 // that intentional?
4989 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
4990 Tok.is(tok::colon))
4991 Data.ColonLoc = ConsumeToken();
4992 } else if (Kind == OMPC_allocate ||
4993 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
4994 PP.getSpelling(Tok) == "iterator")) {
4995 // Handle optional allocator and align modifiers followed by colon
4996 // delimiter.
4997 ColonProtectionRAIIObject ColonRAII(*this);
4998 TentativeParsingAction TPA(*this);
4999 // OpenMP 5.0, 2.10.1, task Construct.
5000 // where aff-modifier is one of the following:
5001 // iterator(iterators-definition)
5002 ExprResult Tail;
5003 if (Kind == OMPC_allocate) {
5004 Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
5005 } else {
5006 HasIterator = true;
5008 Tail = ParseOpenMPIteratorsExpr();
5009 }
5010 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
5011 /*DiscardedValue=*/false);
5012 if (Tail.isUsable() || Data.AllocateAlignment) {
5013 if (Tok.is(tok::colon)) {
5014 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
5015 Data.ColonLoc = ConsumeToken();
5016 TPA.Commit();
5017 } else {
5018 // Colon not found, parse only list of variables.
5019 TPA.Revert();
5020 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
5021 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5023 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
5024 }
5025 }
5026 } else {
5027 // Parsing was unsuccessfull, revert and skip to the end of clause or
5028 // directive.
5029 TPA.Revert();
5030 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5032 }
5033 } else if (Kind == OMPC_adjust_args) {
5034 // Handle adjust-op for adjust_args clause.
5035 ColonProtectionRAIIObject ColonRAII(*this);
5036 Data.ExtraModifier = getOpenMPSimpleClauseType(
5037 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
5038 getLangOpts());
5039 Data.ExtraModifierLoc = Tok.getLocation();
5040 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
5041 Diag(Tok, diag::err_omp_unknown_adjust_args_op)
5042 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
5043 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5044 } else {
5045 ConsumeToken();
5046 if (Tok.is(tok::colon))
5047 Data.ColonLoc = Tok.getLocation();
5048 if (getLangOpts().OpenMP >= 61) {
5049 // Handle the optional fallback argument for the need_device_ptr
5050 // modifier.
5051 if (Tok.is(tok::l_paren)) {
5052 BalancedDelimiterTracker T(*this, tok::l_paren);
5053 T.consumeOpen();
5054 if (Tok.is(tok::identifier)) {
5055 std::string Modifier = PP.getSpelling(Tok);
5056 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
5057 Data.NeedDevicePtrModifier =
5058 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
5059 : OMPC_NEED_DEVICE_PTR_fb_preserve;
5060 } else {
5061 Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);
5062 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5064 return false;
5065 }
5066 ConsumeToken();
5067 if (Tok.is(tok::r_paren)) {
5068 Data.NeedDevicePtrModifierLoc = Tok.getLocation();
5070 } else {
5071 Diag(Tok, diag::err_expected) << tok::r_paren;
5072 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
5074 return false;
5075 }
5076 } else {
5077 Data.NeedDevicePtrModifier = OMPC_NEED_DEVICE_PTR_unknown;
5078 }
5079 }
5080 }
5081 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
5082 "adjust-op");
5083 }
5084 } else if (Kind == OMPC_use_device_ptr) {
5085 // Handle optional fallback modifier for use_device_ptr clause.
5086 // use_device_ptr([fb_preserve | fb_nullify :] list)
5088 if (getLangOpts().OpenMP >= 61 && Tok.is(tok::identifier)) {
5089 auto FallbackModifier = static_cast<OpenMPUseDevicePtrFallbackModifier>(
5090 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
5091 if (FallbackModifier != OMPC_USE_DEVICE_PTR_FALLBACK_unknown) {
5092 Data.ExtraModifier = FallbackModifier;
5093 Data.ExtraModifierLoc = Tok.getLocation();
5094 ConsumeToken();
5095 if (Tok.is(tok::colon))
5096 Data.ColonLoc = ConsumeToken();
5097 else
5098 Diag(Tok, diag::err_modifier_expected_colon) << "fallback";
5099 }
5100 }
5101 } // Handle num_teams clause with optional lower-bound:upper-bound syntax
5102 if (Kind == OMPC_num_teams && !Tok.is(tok::r_paren) &&
5103 !Tok.is(tok::annot_pragma_openmp_end)) {
5105 if (FirstExpr.isInvalid()) {
5106 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5107 Data.RLoc = Tok.getLocation();
5108 if (!T.consumeClose())
5109 Data.RLoc = T.getCloseLocation();
5110 return true;
5111 }
5112
5113 if (Tok.is(tok::colon)) {
5114 // Lower-bound:upper-bound syntax
5115 ConsumeToken();
5117 if (UpperBound.isInvalid()) {
5118 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
5119 Data.RLoc = Tok.getLocation();
5120 if (!T.consumeClose())
5121 Data.RLoc = T.getCloseLocation();
5122 return true;
5123 }
5124 Vars.push_back(FirstExpr.get()); // lower-bound
5125 Vars.push_back(UpperBound.get()); // upper-bound
5126 Data.RLoc = Tok.getLocation();
5127 if (!T.consumeClose())
5128 Data.RLoc = T.getCloseLocation();
5129 return false; // Success
5130 }
5131 if (Tok.is(tok::comma)) {
5132 Vars.push_back(FirstExpr.get());
5133 while (Tok.is(tok::comma)) {
5134 ConsumeToken();
5136 if (NextExpr.isUsable()) {
5137 Vars.push_back(NextExpr.get());
5138 } else {
5139 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5141 break;
5142 }
5143 }
5144 Data.RLoc = Tok.getLocation();
5145 bool HadError = T.consumeClose();
5146 if (!HadError)
5147 Data.RLoc = T.getCloseLocation();
5148 return HadError;
5149 }
5150
5151 // Single value - parse closing paren
5152 Vars.push_back(FirstExpr.get());
5153 Data.RLoc = Tok.getLocation();
5154 if (!T.consumeClose())
5155 Data.RLoc = T.getCloseLocation();
5156 return false; // Success
5157 }
5158
5159 bool IsComma =
5160 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
5161 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
5162 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
5163 (Kind == OMPC_reduction && !InvalidReductionId) ||
5164 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
5165 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
5166 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
5167 (Kind == OMPC_adjust_args &&
5168 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
5169 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
5170 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
5171 Tok.isNot(tok::annot_pragma_openmp_end))) {
5172 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
5173 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
5175 // Parse variable
5177 if (VarExpr.isUsable()) {
5178 Vars.push_back(VarExpr.get());
5179 } else {
5180 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5182 }
5183 }
5184 // Skip ',' if any
5185 IsComma = Tok.is(tok::comma);
5186 if (IsComma)
5187 ConsumeToken();
5188 else if (Tok.isNot(tok::r_paren) &&
5189 Tok.isNot(tok::annot_pragma_openmp_end) &&
5190 (!MayHaveTail || Tok.isNot(tok::colon))) {
5191 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
5192 Diag(Tok, diag::err_omp_expected_punc)
5193 << ((Kind == OMPC_flush)
5194 ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
5195 : getOpenMPClauseName(Kind))
5196 << (Kind == OMPC_flush);
5197 }
5198 }
5199
5200 // Parse ')' for linear clause with modifier.
5201 if (NeedRParenForLinear)
5202 LinearT.consumeClose();
5203 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
5204 // or parse ':' alignment.
5205 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
5206 bool StepFound = false;
5207 bool ModifierFound = false;
5208 if (MustHaveTail) {
5209 Data.ColonLoc = Tok.getLocation();
5211
5212 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
5213 bool Malformed = false;
5214 while (Tok.isNot(tok::r_paren)) {
5215 if (Tok.is(tok::identifier)) {
5216 // identifier could be a linear kind (val, uval, ref) or step
5217 // modifier or step size
5218 OpenMPLinearClauseKind LinKind =
5220 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5221 getLangOpts()));
5222
5223 if (LinKind == OMPC_LINEAR_step) {
5224 if (StepFound)
5225 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
5226
5227 BalancedDelimiterTracker StepT(*this, tok::l_paren,
5228 tok::annot_pragma_openmp_end);
5229 SourceLocation StepModifierLoc = ConsumeToken();
5230 // parse '('
5231 if (StepT.consumeOpen())
5232 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
5233
5234 // parse step size expression
5235 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5236 if (StepFound)
5237 Data.StepModifierLoc = StepModifierLoc;
5238
5239 // parse ')'
5240 StepT.consumeClose();
5241 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
5242 if (ModifierFound)
5243 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
5244
5245 Data.ExtraModifier = LinKind;
5246 Data.ExtraModifierLoc = ConsumeToken();
5247 ModifierFound = true;
5248 } else {
5249 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5250 if (!StepFound) {
5251 Malformed = true;
5252 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5254 }
5255 }
5256 } else {
5257 // parse an integer expression as step size
5258 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
5259 }
5260
5261 if (Tok.is(tok::comma))
5262 ConsumeToken();
5263 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
5264 break;
5265 }
5266 if (!Malformed && !StepFound && !ModifierFound)
5267 Diag(ELoc, diag::err_expected_expression);
5268 } else {
5269 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
5271 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
5272 /*DiscardedValue*/ false);
5273 if (Tail.isUsable())
5274 Data.DepModOrTailExpr = Tail.get();
5275 else
5276 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5278 }
5279 }
5280
5281 // Parse ')'.
5282 Data.RLoc = Tok.getLocation();
5283 if (!T.consumeClose())
5284 Data.RLoc = T.getCloseLocation();
5285 // Exit from scope when the iterator is used in depend clause.
5286 if (HasIterator)
5287 ExitScope();
5288 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5289 Vars.empty()) ||
5290 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5291 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5292}
5293
5294OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5295 OpenMPClauseKind Kind,
5296 bool ParseOnly) {
5297 SourceLocation Loc = Tok.getLocation();
5298 SourceLocation LOpen = ConsumeToken();
5301
5302 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5303 return nullptr;
5304
5305 if (ParseOnly)
5306 return nullptr;
5307 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5308 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5309}
5310
5311bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5312 SourceLocation &ClauseNameLoc,
5313 SourceLocation &OpenLoc,
5314 SourceLocation &CloseLoc,
5316 bool ReqIntConst) {
5317 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5318 "Expected parsing to start at clause name");
5319 ClauseNameLoc = ConsumeToken();
5320
5321 // Parse inside of '(' and ')'.
5322 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5323 if (T.consumeOpen()) {
5324 Diag(Tok, diag::err_expected) << tok::l_paren;
5325 return true;
5326 }
5327
5328 // Parse the list with interleaved commas.
5329 do {
5330 ExprResult Val =
5332 if (!Val.isUsable()) {
5333 // Encountered something other than an expression; abort to ')'.
5334 T.skipToEnd();
5335 return true;
5336 }
5337 Exprs.push_back(Val.get());
5338 } while (TryConsumeToken(tok::comma));
5339
5340 bool Result = T.consumeClose();
5341 OpenLoc = T.getOpenLocation();
5342 CloseLoc = T.getCloseLocation();
5343 return Result;
5344}
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:802
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:8502
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:1525
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:6762
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8713
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:1866
QualType getCanonicalTypeInternal() const
Definition TypeBase.h:3169
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.