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