ParseOpenMP.cpp revision 314564
1193323Sed//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed/// \file 10193323Sed/// \brief This file implements parsing of all OpenMP directives and clauses. 11193323Sed/// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "RAIIObjectsForParser.h" 15193323Sed#include "clang/AST/ASTContext.h" 16193323Sed#include "clang/AST/StmtOpenMP.h" 17193323Sed#include "clang/Parse/ParseDiagnostic.h" 18193323Sed#include "clang/Parse/Parser.h" 19249423Sdim#include "clang/Sema/Scope.h" 20249423Sdim#include "llvm/ADT/PointerIntPair.h" 21193323Sed 22193323Sedusing namespace clang; 23198892Srdivacky 24218893Sdim//===----------------------------------------------------------------------===// 25249423Sdim// OpenMP declarative directives. 26249423Sdim//===----------------------------------------------------------------------===// 27249423Sdim 28249423Sdimnamespace { 29249423Sdimenum OpenMPDirectiveKindEx { 30249423Sdim OMPD_cancellation = OMPD_unknown + 1, 31193323Sed OMPD_data, 32193323Sed OMPD_declare, 33193323Sed OMPD_end, 34193323Sed OMPD_end_declare, 35193323Sed OMPD_enter, 36193323Sed OMPD_exit, 37193323Sed OMPD_point, 38193323Sed OMPD_reduction, 39193323Sed OMPD_target_enter, 40193323Sed OMPD_target_exit, 41193323Sed OMPD_update, 42193323Sed OMPD_distribute_parallel, 43193323Sed OMPD_teams_distribute_parallel, 44193323Sed OMPD_target_teams_distribute_parallel 45193323Sed}; 46193323Sed 47193323Sedclass ThreadprivateListParserHelper final { 48198892Srdivacky SmallVector<Expr *, 4> Identifiers; 49193323Sed Parser *P; 50193323Sed 51193323Sedpublic: 52212904Sdim ThreadprivateListParserHelper(Parser *P) : P(P) {} 53193323Sed void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 54193323Sed ExprResult Res = 55193323Sed P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo); 56193323Sed if (Res.isUsable()) 57212904Sdim Identifiers.push_back(Res.get()); 58193323Sed } 59212904Sdim llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 60212904Sdim}; 61193323Sed} // namespace 62193323Sed 63193323Sed// Map token string to extended OMP token kind that are 64193323Sed// OpenMPDirectiveKind + OpenMPDirectiveKindEx. 65193323Sedstatic unsigned getOpenMPDirectiveKindEx(StringRef S) { 66193323Sed auto DKind = getOpenMPDirectiveKind(S); 67193323Sed if (DKind != OMPD_unknown) 68193323Sed return DKind; 69193323Sed 70193323Sed return llvm::StringSwitch<unsigned>(S) 71193323Sed .Case("cancellation", OMPD_cancellation) 72193323Sed .Case("data", OMPD_data) 73193323Sed .Case("declare", OMPD_declare) 74198892Srdivacky .Case("end", OMPD_end) 75193323Sed .Case("enter", OMPD_enter) 76193323Sed .Case("exit", OMPD_exit) 77212904Sdim .Case("point", OMPD_point) 78193323Sed .Case("reduction", OMPD_reduction) 79193323Sed .Case("update", OMPD_update) 80193323Sed .Default(OMPD_unknown); 81212904Sdim} 82193323Sed 83193323Sedstatic OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { 84193323Sed // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 85212904Sdim // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 86193323Sed // TODO: add other combined directives in topological order. 87193323Sed static const unsigned F[][3] = { 88193323Sed { OMPD_cancellation, OMPD_point, OMPD_cancellation_point }, 89212904Sdim { OMPD_declare, OMPD_reduction, OMPD_declare_reduction }, 90193323Sed { OMPD_declare, OMPD_simd, OMPD_declare_simd }, 91193323Sed { OMPD_declare, OMPD_target, OMPD_declare_target }, 92193323Sed { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel }, 93218893Sdim { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for }, 94218893Sdim { OMPD_distribute_parallel_for, OMPD_simd, 95218893Sdim OMPD_distribute_parallel_for_simd }, 96193323Sed { OMPD_distribute, OMPD_simd, OMPD_distribute_simd }, 97193323Sed { OMPD_end, OMPD_declare, OMPD_end_declare }, 98193323Sed { OMPD_end_declare, OMPD_target, OMPD_end_declare_target }, 99193323Sed { OMPD_target, OMPD_data, OMPD_target_data }, 100193323Sed { OMPD_target, OMPD_enter, OMPD_target_enter }, 101193323Sed { OMPD_target, OMPD_exit, OMPD_target_exit }, 102193323Sed { OMPD_target, OMPD_update, OMPD_target_update }, 103193323Sed { OMPD_target_enter, OMPD_data, OMPD_target_enter_data }, 104193323Sed { OMPD_target_exit, OMPD_data, OMPD_target_exit_data }, 105193323Sed { OMPD_for, OMPD_simd, OMPD_for_simd }, 106193323Sed { OMPD_parallel, OMPD_for, OMPD_parallel_for }, 107193323Sed { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd }, 108193323Sed { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }, 109193323Sed { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd }, 110193323Sed { OMPD_target, OMPD_parallel, OMPD_target_parallel }, 111193323Sed { OMPD_target, OMPD_simd, OMPD_target_simd }, 112193323Sed { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for }, 113218893Sdim { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd }, 114212904Sdim { OMPD_teams, OMPD_distribute, OMPD_teams_distribute }, 115218893Sdim { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd }, 116212904Sdim { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel }, 117212904Sdim { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for }, 118212904Sdim { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd }, 119193323Sed { OMPD_target, OMPD_teams, OMPD_target_teams }, 120193323Sed { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute }, 121193323Sed { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel }, 122193323Sed { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd }, 123193323Sed { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for }, 124212904Sdim { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd } 125218893Sdim }; 126218893Sdim enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 127193323Sed auto Tok = P.getCurToken(); 128193323Sed unsigned DKind = 129218893Sdim Tok.isAnnotation() 130193323Sed ? static_cast<unsigned>(OMPD_unknown) 131218893Sdim : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 132193323Sed if (DKind == OMPD_unknown) 133218893Sdim return OMPD_unknown; 134218893Sdim 135193323Sed for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { 136193323Sed if (DKind != F[i][0]) 137193323Sed continue; 138193323Sed 139193323Sed Tok = P.getPreprocessor().LookAhead(0); 140212904Sdim unsigned SDKind = 141218893Sdim Tok.isAnnotation() 142218893Sdim ? static_cast<unsigned>(OMPD_unknown) 143218893Sdim : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 144218893Sdim if (SDKind == OMPD_unknown) 145218893Sdim continue; 146218893Sdim 147218893Sdim if (SDKind == F[i][1]) { 148218893Sdim P.ConsumeToken(); 149218893Sdim DKind = F[i][2]; 150218893Sdim } 151218893Sdim } 152193323Sed return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind) 153193323Sed : OMPD_unknown; 154193323Sed} 155193323Sed 156218893Sdimstatic DeclarationName parseOpenMPReductionId(Parser &P) { 157193323Sed Token Tok = P.getCurToken(); 158202878Srdivacky Sema &Actions = P.getActions(); 159202878Srdivacky OverloadedOperatorKind OOK = OO_None; 160202878Srdivacky // Allow to use 'operator' keyword for C++ operators 161202878Srdivacky bool WithOperator = false; 162212904Sdim if (Tok.is(tok::kw_operator)) { 163212904Sdim P.ConsumeToken(); 164202878Srdivacky Tok = P.getCurToken(); 165202878Srdivacky WithOperator = true; 166202878Srdivacky } 167202878Srdivacky switch (Tok.getKind()) { 168193323Sed case tok::plus: // '+' 169193323Sed OOK = OO_Plus; 170193323Sed break; 171212904Sdim case tok::minus: // '-' 172212904Sdim OOK = OO_Minus; 173212904Sdim break; 174193323Sed case tok::star: // '*' 175193323Sed OOK = OO_Star; 176193323Sed break; 177193323Sed case tok::amp: // '&' 178193323Sed OOK = OO_Amp; 179193323Sed break; 180193323Sed case tok::pipe: // '|' 181193323Sed OOK = OO_Pipe; 182193323Sed break; 183193323Sed case tok::caret: // '^' 184193323Sed OOK = OO_Caret; 185193323Sed break; 186193323Sed case tok::ampamp: // '&&' 187193323Sed OOK = OO_AmpAmp; 188193323Sed break; 189218893Sdim case tok::pipepipe: // '||' 190212904Sdim OOK = OO_PipePipe; 191218893Sdim break; 192263508Sdim case tok::identifier: // identifier 193218893Sdim if (!WithOperator) 194218893Sdim break; 195218893Sdim default: 196193323Sed P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 197193323Sed P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 198193323Sed Parser::StopBeforeMatch); 199193323Sed return DeclarationName(); 200193323Sed } 201193323Sed P.ConsumeToken(); 202193323Sed auto &DeclNames = Actions.getASTContext().DeclarationNames; 203193323Sed return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 204193323Sed : DeclNames.getCXXOperatorName(OOK); 205193323Sed} 206193323Sed 207193323Sed/// \brief Parse 'omp declare reduction' construct. 208193323Sed/// 209193323Sed/// declare-reduction-directive: 210193323Sed/// annot_pragma_openmp 'declare' 'reduction' 211193323Sed/// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 212193323Sed/// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 213193323Sed/// annot_pragma_openmp_end 214193323Sed/// <reduction_id> is either a base language identifier or one of the following 215193323Sed/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 216193323Sed/// 217193323SedParser::DeclGroupPtrTy 218193323SedParser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 219193323Sed // Parse '('. 220193323Sed BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 221193323Sed if (T.expectAndConsume(diag::err_expected_lparen_after, 222193323Sed getOpenMPDirectiveName(OMPD_declare_reduction))) { 223193323Sed SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 224193323Sed return DeclGroupPtrTy(); 225193323Sed } 226193323Sed 227193323Sed DeclarationName Name = parseOpenMPReductionId(*this); 228193323Sed if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 229193323Sed return DeclGroupPtrTy(); 230193323Sed 231204642Srdivacky // Consume ':'. 232193323Sed bool IsCorrect = !ExpectAndConsume(tok::colon); 233193323Sed 234193323Sed if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 235193323Sed return DeclGroupPtrTy(); 236193323Sed 237193323Sed IsCorrect = IsCorrect && !Name.isEmpty(); 238193323Sed 239193323Sed if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 240193323Sed Diag(Tok.getLocation(), diag::err_expected_type); 241193323Sed IsCorrect = false; 242193323Sed } 243193323Sed 244193323Sed if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 245193323Sed return DeclGroupPtrTy(); 246193323Sed 247193323Sed SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 248193323Sed // Parse list of types until ':' token. 249204642Srdivacky do { 250193323Sed ColonProtectionRAIIObject ColonRAII(*this); 251210299Sed SourceRange Range; 252210299Sed TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS); 253210299Sed if (TR.isUsable()) { 254193323Sed auto ReductionType = 255210299Sed Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 256193323Sed if (!ReductionType.isNull()) { 257193323Sed ReductionTypes.push_back( 258193323Sed std::make_pair(ReductionType, Range.getBegin())); 259193323Sed } 260193323Sed } else { 261210299Sed SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 262193323Sed StopBeforeMatch); 263210299Sed } 264198090Srdivacky 265198090Srdivacky if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 266243830Sdim break; 267210299Sed 268210299Sed // Consume ','. 269193323Sed if (ExpectAndConsume(tok::comma)) { 270193323Sed IsCorrect = false; 271210299Sed if (Tok.is(tok::annot_pragma_openmp_end)) { 272210299Sed Diag(Tok.getLocation(), diag::err_expected_type); 273210299Sed return DeclGroupPtrTy(); 274193323Sed } 275193323Sed } 276210299Sed } while (Tok.isNot(tok::annot_pragma_openmp_end)); 277210299Sed 278210299Sed if (ReductionTypes.empty()) { 279193323Sed SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 280193323Sed return DeclGroupPtrTy(); 281193323Sed } 282193323Sed 283193323Sed if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 284193323Sed return DeclGroupPtrTy(); 285193323Sed 286210299Sed // Consume ':'. 287193323Sed if (ExpectAndConsume(tok::colon)) 288193323Sed IsCorrect = false; 289193323Sed 290193323Sed if (Tok.is(tok::annot_pragma_openmp_end)) { 291193323Sed Diag(Tok.getLocation(), diag::err_expected_expression); 292210299Sed return DeclGroupPtrTy(); 293210299Sed } 294193323Sed 295193323Sed DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 296193323Sed getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 297193323Sed 298193323Sed // Parse <combiner> expression and then parse initializer if any for each 299193323Sed // correct type. 300193323Sed unsigned I = 0, E = ReductionTypes.size(); 301193323Sed for (auto *D : DRD.get()) { 302193323Sed TentativeParsingAction TPA(*this); 303193323Sed ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 304193323Sed Scope::OpenMPDirectiveScope); 305193323Sed // Parse <combiner> expression. 306193323Sed Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 307193323Sed ExprResult CombinerResult = 308193323Sed Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), 309193323Sed D->getLocation(), /*DiscardedValue=*/true); 310193323Sed Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 311193323Sed 312210299Sed if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 313210299Sed Tok.isNot(tok::annot_pragma_openmp_end)) { 314193323Sed TPA.Commit(); 315193323Sed IsCorrect = false; 316193323Sed break; 317193323Sed } 318193323Sed IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 319193323Sed ExprResult InitializerResult; 320193323Sed if (Tok.isNot(tok::annot_pragma_openmp_end)) { 321210299Sed // Parse <initializer> expression. 322193323Sed if (Tok.is(tok::identifier) && 323193323Sed Tok.getIdentifierInfo()->isStr("initializer")) 324193323Sed ConsumeToken(); 325193323Sed else { 326193323Sed Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 327193323Sed TPA.Commit(); 328193323Sed IsCorrect = false; 329193323Sed break; 330218893Sdim } 331193323Sed // Parse '('. 332243830Sdim BalancedDelimiterTracker T(*this, tok::l_paren, 333193323Sed tok::annot_pragma_openmp_end); 334193323Sed IsCorrect = 335193323Sed !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 336193323Sed IsCorrect; 337193323Sed if (Tok.isNot(tok::annot_pragma_openmp_end)) { 338193323Sed ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 339193323Sed Scope::OpenMPDirectiveScope); 340193323Sed // Parse expression. 341193323Sed Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D); 342193323Sed InitializerResult = Actions.ActOnFinishFullExpr( 343193323Sed ParseAssignmentExpression().get(), D->getLocation(), 344193323Sed /*DiscardedValue=*/true); 345193323Sed Actions.ActOnOpenMPDeclareReductionInitializerEnd( 346193323Sed D, InitializerResult.get()); 347193323Sed if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 348193323Sed Tok.isNot(tok::annot_pragma_openmp_end)) { 349193323Sed TPA.Commit(); 350193323Sed IsCorrect = false; 351193323Sed break; 352193323Sed } 353193323Sed IsCorrect = 354193323Sed !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 355193323Sed } 356193323Sed } 357193323Sed 358193323Sed ++I; 359193323Sed // Revert parsing if not the last type, otherwise accept it, we're done with 360193323Sed // parsing. 361193323Sed if (I != E) 362193323Sed TPA.Revert(); 363193323Sed else 364193323Sed TPA.Commit(); 365193323Sed } 366193323Sed return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 367193323Sed IsCorrect); 368193323Sed} 369193323Sed 370193323Sednamespace { 371193323Sed/// RAII that recreates function context for correct parsing of clauses of 372193323Sed/// 'declare simd' construct. 373193323Sed/// OpenMP, 2.8.2 declare simd Construct 374193323Sed/// The expressions appearing in the clauses of this directive are evaluated in 375193323Sed/// the scope of the arguments of the function declaration or definition. 376193323Sedclass FNContextRAII final { 377193323Sed Parser &P; 378193323Sed Sema::CXXThisScopeRAII *ThisScope; 379193323Sed Parser::ParseScope *TempScope; 380193323Sed Parser::ParseScope *FnScope; 381193323Sed bool HasTemplateScope = false; 382193323Sed bool HasFunScope = false; 383193323Sed FNContextRAII() = delete; 384193323Sed FNContextRAII(const FNContextRAII &) = delete; 385193323Sed FNContextRAII &operator=(const FNContextRAII &) = delete; 386193323Sed 387193323Sedpublic: 388193323Sed FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) { 389193323Sed Decl *D = *Ptr.get().begin(); 390193323Sed NamedDecl *ND = dyn_cast<NamedDecl>(D); 391193323Sed RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 392193323Sed Sema &Actions = P.getActions(); 393193323Sed 394193323Sed // Allow 'this' within late-parsed attributes. 395193323Sed ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0, 396193323Sed ND && ND->isCXXInstanceMember()); 397193323Sed 398193323Sed // If the Decl is templatized, add template parameters to scope. 399193323Sed HasTemplateScope = D->isTemplateDecl(); 400193323Sed TempScope = 401193323Sed new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope); 402193323Sed if (HasTemplateScope) 403193323Sed Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D); 404193323Sed 405193323Sed // If the Decl is on a function, add function parameters to the scope. 406193323Sed HasFunScope = D->isFunctionOrFunctionTemplate(); 407193323Sed FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope, 408193323Sed HasFunScope); 409193323Sed if (HasFunScope) 410193323Sed Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 411193323Sed } 412193323Sed ~FNContextRAII() { 413193323Sed if (HasFunScope) { 414193323Sed P.getActions().ActOnExitFunctionContext(); 415193323Sed FnScope->Exit(); // Pop scope, and remove Decls from IdResolver 416193323Sed } 417193323Sed if (HasTemplateScope) 418193323Sed TempScope->Exit(); 419193323Sed delete FnScope; 420212904Sdim delete TempScope; 421193323Sed delete ThisScope; 422193323Sed } 423193323Sed}; 424193323Sed} // namespace 425193323Sed 426193323Sed/// Parses clauses for 'declare simd' directive. 427193323Sed/// clause: 428193323Sed/// 'inbranch' | 'notinbranch' 429193323Sed/// 'simdlen' '(' <expr> ')' 430193323Sed/// { 'uniform' '(' <argument_list> ')' } 431193323Sed/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 432193323Sed/// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 433193323Sedstatic bool parseDeclareSimdClauses( 434193323Sed Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 435193323Sed SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 436193323Sed SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 437193323Sed SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 438193323Sed SourceRange BSRange; 439193323Sed const Token &Tok = P.getCurToken(); 440193323Sed bool IsError = false; 441193323Sed while (Tok.isNot(tok::annot_pragma_openmp_end)) { 442193323Sed if (Tok.isNot(tok::identifier)) 443193323Sed break; 444193323Sed OMPDeclareSimdDeclAttr::BranchStateTy Out; 445193323Sed IdentifierInfo *II = Tok.getIdentifierInfo(); 446193323Sed StringRef ClauseName = II->getName(); 447193323Sed // Parse 'inranch|notinbranch' clauses. 448193323Sed if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 449193323Sed if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 450239462Sdim P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 451193323Sed << ClauseName 452239462Sdim << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 453193323Sed IsError = true; 454193323Sed } 455193323Sed BS = Out; 456239462Sdim BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 457193323Sed P.ConsumeToken(); 458239462Sdim } else if (ClauseName.equals("simdlen")) { 459193323Sed if (SimdLen.isUsable()) { 460193323Sed P.Diag(Tok, diag::err_omp_more_one_clause) 461243830Sdim << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 462193323Sed IsError = true; 463234353Sdim } 464234353Sdim P.ConsumeToken(); 465234353Sdim SourceLocation RLoc; 466234353Sdim SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 467234353Sdim if (SimdLen.isInvalid()) 468193323Sed IsError = true; 469193323Sed } else { 470193323Sed OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 471193323Sed if (CKind == OMPC_uniform || CKind == OMPC_aligned || 472193323Sed CKind == OMPC_linear) { 473193323Sed Parser::OpenMPVarListDataTy Data; 474193323Sed auto *Vars = &Uniforms; 475193323Sed if (CKind == OMPC_aligned) 476193323Sed Vars = &Aligneds; 477193323Sed else if (CKind == OMPC_linear) 478193323Sed Vars = &Linears; 479193323Sed 480193323Sed P.ConsumeToken(); 481193323Sed if (P.ParseOpenMPVarList(OMPD_declare_simd, 482193323Sed getOpenMPClauseKind(ClauseName), *Vars, Data)) 483193323Sed IsError = true; 484193323Sed if (CKind == OMPC_aligned) 485193323Sed Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); 486193323Sed else if (CKind == OMPC_linear) { 487193323Sed if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind, 488193323Sed Data.DepLinMapLoc)) 489218893Sdim Data.LinKind = OMPC_LINEAR_val; 490218893Sdim LinModifiers.append(Linears.size() - LinModifiers.size(), 491193323Sed Data.LinKind); 492218893Sdim Steps.append(Linears.size() - Steps.size(), Data.TailExpr); 493218893Sdim } 494193323Sed } else 495193323Sed // TODO: add parsing of other clauses. 496193323Sed break; 497212904Sdim } 498212904Sdim // Skip ',' if any. 499193323Sed if (Tok.is(tok::comma)) 500193323Sed P.ConsumeToken(); 501193323Sed } 502193323Sed return IsError; 503193323Sed} 504193323Sed 505203954Srdivacky/// Parse clauses for '#pragma omp declare simd'. 506193323SedParser::DeclGroupPtrTy 507193323SedParser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 508193323Sed CachedTokens &Toks, SourceLocation Loc) { 509193323Sed PP.EnterToken(Tok); 510193323Sed PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); 511193323Sed // Consume the previously pushed token. 512193323Sed ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 513193323Sed 514193323Sed FNContextRAII FnContext(*this, Ptr); 515193323Sed OMPDeclareSimdDeclAttr::BranchStateTy BS = 516193323Sed OMPDeclareSimdDeclAttr::BS_Undefined; 517193323Sed ExprResult Simdlen; 518212904Sdim SmallVector<Expr *, 4> Uniforms; 519193323Sed SmallVector<Expr *, 4> Aligneds; 520193323Sed SmallVector<Expr *, 4> Alignments; 521193323Sed SmallVector<Expr *, 4> Linears; 522212904Sdim SmallVector<unsigned, 4> LinModifiers; 523212904Sdim SmallVector<Expr *, 4> Steps; 524193323Sed bool IsError = 525193323Sed parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 526193323Sed Alignments, Linears, LinModifiers, Steps); 527193323Sed // Need to check for extra tokens. 528193323Sed if (Tok.isNot(tok::annot_pragma_openmp_end)) { 529193323Sed Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 530193323Sed << getOpenMPDirectiveName(OMPD_declare_simd); 531193323Sed while (Tok.isNot(tok::annot_pragma_openmp_end)) 532193323Sed ConsumeAnyToken(); 533193323Sed } 534193323Sed // Skip the last annot_pragma_openmp_end. 535193323Sed SourceLocation EndLoc = ConsumeToken(); 536193323Sed if (!IsError) { 537193323Sed return Actions.ActOnOpenMPDeclareSimdDirective( 538193323Sed Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 539193323Sed LinModifiers, Steps, SourceRange(Loc, EndLoc)); 540193323Sed } 541218893Sdim return Ptr; 542193323Sed} 543193323Sed 544193323Sed/// \brief Parsing of declarative OpenMP directives. 545212904Sdim/// 546218893Sdim/// threadprivate-directive: 547193323Sed/// annot_pragma_openmp 'threadprivate' simple-variable-list 548193323Sed/// annot_pragma_openmp_end 549193323Sed/// 550193323Sed/// declare-reduction-directive: 551218893Sdim/// annot_pragma_openmp 'declare' 'reduction' [...] 552218893Sdim/// annot_pragma_openmp_end 553193323Sed/// 554212904Sdim/// declare-simd-directive: 555193323Sed/// annot_pragma_openmp 'declare simd' {<clause> [,]} 556212904Sdim/// annot_pragma_openmp_end 557193323Sed/// <function declaration/definition> 558193323Sed/// 559193323SedParser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 560193323Sed AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, 561218893Sdim DeclSpec::TST TagType, Decl *Tag) { 562193323Sed assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 563193323Sed ParenBraceBracketBalancer BalancerRAIIObj(*this); 564193323Sed 565193323Sed SourceLocation Loc = ConsumeToken(); 566193323Sed auto DKind = ParseOpenMPDirectiveKind(*this); 567193323Sed 568193323Sed switch (DKind) { 569193323Sed case OMPD_threadprivate: { 570193323Sed ConsumeToken(); 571193323Sed ThreadprivateListParserHelper Helper(this); 572193323Sed if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) { 573193323Sed // The last seen token is annot_pragma_openmp_end - need to check for 574193323Sed // extra tokens. 575212904Sdim if (Tok.isNot(tok::annot_pragma_openmp_end)) { 576193323Sed Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 577193323Sed << getOpenMPDirectiveName(OMPD_threadprivate); 578193323Sed SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 579193323Sed } 580193323Sed // Skip the last annot_pragma_openmp_end. 581193323Sed ConsumeToken(); 582193323Sed return Actions.ActOnOpenMPThreadprivateDirective(Loc, 583193323Sed Helper.getIdentifiers()); 584193323Sed } 585193323Sed break; 586193323Sed } 587193323Sed case OMPD_declare_reduction: 588193323Sed ConsumeToken(); 589193323Sed if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) { 590193323Sed // The last seen token is annot_pragma_openmp_end - need to check for 591193323Sed // extra tokens. 592193323Sed if (Tok.isNot(tok::annot_pragma_openmp_end)) { 593193323Sed Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 594193323Sed << getOpenMPDirectiveName(OMPD_declare_reduction); 595193323Sed while (Tok.isNot(tok::annot_pragma_openmp_end)) 596193323Sed ConsumeAnyToken(); 597193323Sed } 598218893Sdim // Skip the last annot_pragma_openmp_end. 599218893Sdim ConsumeToken(); 600218893Sdim return Res; 601218893Sdim } 602218893Sdim break; 603221345Sdim case OMPD_declare_simd: { 604218893Sdim // The syntax is: 605218893Sdim // { #pragma omp declare simd } 606218893Sdim // <function-declaration-or-definition> 607218893Sdim // 608 ConsumeToken(); 609 CachedTokens Toks; 610 while(Tok.isNot(tok::annot_pragma_openmp_end)) { 611 Toks.push_back(Tok); 612 ConsumeAnyToken(); 613 } 614 Toks.push_back(Tok); 615 ConsumeAnyToken(); 616 617 DeclGroupPtrTy Ptr; 618 if (Tok.is(tok::annot_pragma_openmp)) 619 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); 620 else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 621 // Here we expect to see some function declaration. 622 if (AS == AS_none) { 623 assert(TagType == DeclSpec::TST_unspecified); 624 MaybeParseCXX11Attributes(Attrs); 625 ParsingDeclSpec PDS(*this); 626 Ptr = ParseExternalDeclaration(Attrs, &PDS); 627 } else { 628 Ptr = 629 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 630 } 631 } 632 if (!Ptr) { 633 Diag(Loc, diag::err_omp_decl_in_declare_simd); 634 return DeclGroupPtrTy(); 635 } 636 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 637 } 638 case OMPD_declare_target: { 639 SourceLocation DTLoc = ConsumeAnyToken(); 640 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 641 // OpenMP 4.5 syntax with list of entities. 642 llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls; 643 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 644 OMPDeclareTargetDeclAttr::MapTypeTy MT = 645 OMPDeclareTargetDeclAttr::MT_To; 646 if (Tok.is(tok::identifier)) { 647 IdentifierInfo *II = Tok.getIdentifierInfo(); 648 StringRef ClauseName = II->getName(); 649 // Parse 'to|link' clauses. 650 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, 651 MT)) { 652 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 653 << ClauseName; 654 break; 655 } 656 ConsumeToken(); 657 } 658 auto Callback = [this, MT, &SameDirectiveDecls]( 659 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 660 Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, 661 SameDirectiveDecls); 662 }; 663 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true)) 664 break; 665 666 // Consume optional ','. 667 if (Tok.is(tok::comma)) 668 ConsumeToken(); 669 } 670 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 671 ConsumeAnyToken(); 672 return DeclGroupPtrTy(); 673 } 674 675 // Skip the last annot_pragma_openmp_end. 676 ConsumeAnyToken(); 677 678 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 679 return DeclGroupPtrTy(); 680 681 DKind = ParseOpenMPDirectiveKind(*this); 682 while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target && 683 Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) { 684 ParsedAttributesWithRange attrs(AttrFactory); 685 MaybeParseCXX11Attributes(attrs); 686 ParseExternalDeclaration(attrs); 687 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 688 TentativeParsingAction TPA(*this); 689 ConsumeToken(); 690 DKind = ParseOpenMPDirectiveKind(*this); 691 if (DKind != OMPD_end_declare_target) 692 TPA.Revert(); 693 else 694 TPA.Commit(); 695 } 696 } 697 698 if (DKind == OMPD_end_declare_target) { 699 ConsumeAnyToken(); 700 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 701 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 702 << getOpenMPDirectiveName(OMPD_end_declare_target); 703 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 704 } 705 // Skip the last annot_pragma_openmp_end. 706 ConsumeAnyToken(); 707 } else { 708 Diag(Tok, diag::err_expected_end_declare_target); 709 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; 710 } 711 Actions.ActOnFinishOpenMPDeclareTargetDirective(); 712 return DeclGroupPtrTy(); 713 } 714 case OMPD_unknown: 715 Diag(Tok, diag::err_omp_unknown_directive); 716 break; 717 case OMPD_parallel: 718 case OMPD_simd: 719 case OMPD_task: 720 case OMPD_taskyield: 721 case OMPD_barrier: 722 case OMPD_taskwait: 723 case OMPD_taskgroup: 724 case OMPD_flush: 725 case OMPD_for: 726 case OMPD_for_simd: 727 case OMPD_sections: 728 case OMPD_section: 729 case OMPD_single: 730 case OMPD_master: 731 case OMPD_ordered: 732 case OMPD_critical: 733 case OMPD_parallel_for: 734 case OMPD_parallel_for_simd: 735 case OMPD_parallel_sections: 736 case OMPD_atomic: 737 case OMPD_target: 738 case OMPD_teams: 739 case OMPD_cancellation_point: 740 case OMPD_cancel: 741 case OMPD_target_data: 742 case OMPD_target_enter_data: 743 case OMPD_target_exit_data: 744 case OMPD_target_parallel: 745 case OMPD_target_parallel_for: 746 case OMPD_taskloop: 747 case OMPD_taskloop_simd: 748 case OMPD_distribute: 749 case OMPD_end_declare_target: 750 case OMPD_target_update: 751 case OMPD_distribute_parallel_for: 752 case OMPD_distribute_parallel_for_simd: 753 case OMPD_distribute_simd: 754 case OMPD_target_parallel_for_simd: 755 case OMPD_target_simd: 756 case OMPD_teams_distribute: 757 case OMPD_teams_distribute_simd: 758 case OMPD_teams_distribute_parallel_for_simd: 759 case OMPD_teams_distribute_parallel_for: 760 case OMPD_target_teams: 761 case OMPD_target_teams_distribute: 762 case OMPD_target_teams_distribute_parallel_for: 763 case OMPD_target_teams_distribute_parallel_for_simd: 764 case OMPD_target_teams_distribute_simd: 765 Diag(Tok, diag::err_omp_unexpected_directive) 766 << getOpenMPDirectiveName(DKind); 767 break; 768 } 769 while (Tok.isNot(tok::annot_pragma_openmp_end)) 770 ConsumeAnyToken(); 771 ConsumeAnyToken(); 772 return nullptr; 773} 774 775/// \brief Parsing of declarative or executable OpenMP directives. 776/// 777/// threadprivate-directive: 778/// annot_pragma_openmp 'threadprivate' simple-variable-list 779/// annot_pragma_openmp_end 780/// 781/// declare-reduction-directive: 782/// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 783/// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 784/// ('omp_priv' '=' <expression>|<function_call>) ')'] 785/// annot_pragma_openmp_end 786/// 787/// executable-directive: 788/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 789/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 790/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | 791/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | 792/// 'for simd' | 'parallel for simd' | 'target' | 'target data' | 793/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 794/// 'distribute' | 'target enter data' | 'target exit data' | 795/// 'target parallel' | 'target parallel for' | 796/// 'target update' | 'distribute parallel for' | 797/// 'distribute paralle for simd' | 'distribute simd' | 798/// 'target parallel for simd' | 'target simd' | 799/// 'teams distribute' | 'teams distribute simd' | 800/// 'teams distribute parallel for simd' | 801/// 'teams distribute parallel for' | 'target teams' | 802/// 'target teams distribute' | 803/// 'target teams distribute parallel for' | 804/// 'target teams distribute parallel for simd' | 805/// 'target teams distribute simd' {clause} 806/// annot_pragma_openmp_end 807/// 808StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( 809 AllowedContsructsKind Allowed) { 810 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 811 ParenBraceBracketBalancer BalancerRAIIObj(*this); 812 SmallVector<OMPClause *, 5> Clauses; 813 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 814 FirstClauses(OMPC_unknown + 1); 815 unsigned ScopeFlags = 816 Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; 817 SourceLocation Loc = ConsumeToken(), EndLoc; 818 auto DKind = ParseOpenMPDirectiveKind(*this); 819 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 820 // Name of critical directive. 821 DeclarationNameInfo DirName; 822 StmtResult Directive = StmtError(); 823 bool HasAssociatedStatement = true; 824 bool FlushHasClause = false; 825 826 switch (DKind) { 827 case OMPD_threadprivate: { 828 if (Allowed != ACK_Any) { 829 Diag(Tok, diag::err_omp_immediate_directive) 830 << getOpenMPDirectiveName(DKind) << 0; 831 } 832 ConsumeToken(); 833 ThreadprivateListParserHelper Helper(this); 834 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) { 835 // The last seen token is annot_pragma_openmp_end - need to check for 836 // extra tokens. 837 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 838 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 839 << getOpenMPDirectiveName(OMPD_threadprivate); 840 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 841 } 842 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 843 Loc, Helper.getIdentifiers()); 844 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 845 } 846 SkipUntil(tok::annot_pragma_openmp_end); 847 break; 848 } 849 case OMPD_declare_reduction: 850 ConsumeToken(); 851 if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 852 // The last seen token is annot_pragma_openmp_end - need to check for 853 // extra tokens. 854 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 855 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 856 << getOpenMPDirectiveName(OMPD_declare_reduction); 857 while (Tok.isNot(tok::annot_pragma_openmp_end)) 858 ConsumeAnyToken(); 859 } 860 ConsumeAnyToken(); 861 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 862 } else 863 SkipUntil(tok::annot_pragma_openmp_end); 864 break; 865 case OMPD_flush: 866 if (PP.LookAhead(0).is(tok::l_paren)) { 867 FlushHasClause = true; 868 // Push copy of the current token back to stream to properly parse 869 // pseudo-clause OMPFlushClause. 870 PP.EnterToken(Tok); 871 } 872 case OMPD_taskyield: 873 case OMPD_barrier: 874 case OMPD_taskwait: 875 case OMPD_cancellation_point: 876 case OMPD_cancel: 877 case OMPD_target_enter_data: 878 case OMPD_target_exit_data: 879 case OMPD_target_update: 880 if (Allowed == ACK_StatementsOpenMPNonStandalone) { 881 Diag(Tok, diag::err_omp_immediate_directive) 882 << getOpenMPDirectiveName(DKind) << 0; 883 } 884 HasAssociatedStatement = false; 885 // Fall through for further analysis. 886 case OMPD_parallel: 887 case OMPD_simd: 888 case OMPD_for: 889 case OMPD_for_simd: 890 case OMPD_sections: 891 case OMPD_single: 892 case OMPD_section: 893 case OMPD_master: 894 case OMPD_critical: 895 case OMPD_parallel_for: 896 case OMPD_parallel_for_simd: 897 case OMPD_parallel_sections: 898 case OMPD_task: 899 case OMPD_ordered: 900 case OMPD_atomic: 901 case OMPD_target: 902 case OMPD_teams: 903 case OMPD_taskgroup: 904 case OMPD_target_data: 905 case OMPD_target_parallel: 906 case OMPD_target_parallel_for: 907 case OMPD_taskloop: 908 case OMPD_taskloop_simd: 909 case OMPD_distribute: 910 case OMPD_distribute_parallel_for: 911 case OMPD_distribute_parallel_for_simd: 912 case OMPD_distribute_simd: 913 case OMPD_target_parallel_for_simd: 914 case OMPD_target_simd: 915 case OMPD_teams_distribute: 916 case OMPD_teams_distribute_simd: 917 case OMPD_teams_distribute_parallel_for_simd: 918 case OMPD_teams_distribute_parallel_for: 919 case OMPD_target_teams: 920 case OMPD_target_teams_distribute: 921 case OMPD_target_teams_distribute_parallel_for: 922 case OMPD_target_teams_distribute_parallel_for_simd: 923 case OMPD_target_teams_distribute_simd: { 924 ConsumeToken(); 925 // Parse directive name of the 'critical' directive if any. 926 if (DKind == OMPD_critical) { 927 BalancedDelimiterTracker T(*this, tok::l_paren, 928 tok::annot_pragma_openmp_end); 929 if (!T.consumeOpen()) { 930 if (Tok.isAnyIdentifier()) { 931 DirName = 932 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 933 ConsumeAnyToken(); 934 } else { 935 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 936 } 937 T.consumeClose(); 938 } 939 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 940 CancelRegion = ParseOpenMPDirectiveKind(*this); 941 if (Tok.isNot(tok::annot_pragma_openmp_end)) 942 ConsumeToken(); 943 } 944 945 if (isOpenMPLoopDirective(DKind)) 946 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 947 if (isOpenMPSimdDirective(DKind)) 948 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 949 ParseScope OMPDirectiveScope(this, ScopeFlags); 950 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 951 952 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 953 OpenMPClauseKind CKind = 954 Tok.isAnnotation() 955 ? OMPC_unknown 956 : FlushHasClause ? OMPC_flush 957 : getOpenMPClauseKind(PP.getSpelling(Tok)); 958 Actions.StartOpenMPClause(CKind); 959 FlushHasClause = false; 960 OMPClause *Clause = 961 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); 962 FirstClauses[CKind].setInt(true); 963 if (Clause) { 964 FirstClauses[CKind].setPointer(Clause); 965 Clauses.push_back(Clause); 966 } 967 968 // Skip ',' if any. 969 if (Tok.is(tok::comma)) 970 ConsumeToken(); 971 Actions.EndOpenMPClause(); 972 } 973 // End location of the directive. 974 EndLoc = Tok.getLocation(); 975 // Consume final annot_pragma_openmp_end. 976 ConsumeToken(); 977 978 // OpenMP [2.13.8, ordered Construct, Syntax] 979 // If the depend clause is specified, the ordered construct is a stand-alone 980 // directive. 981 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { 982 if (Allowed == ACK_StatementsOpenMPNonStandalone) { 983 Diag(Loc, diag::err_omp_immediate_directive) 984 << getOpenMPDirectiveName(DKind) << 1 985 << getOpenMPClauseName(OMPC_depend); 986 } 987 HasAssociatedStatement = false; 988 } 989 990 StmtResult AssociatedStmt; 991 if (HasAssociatedStatement) { 992 // The body is a block scope like in Lambdas and Blocks. 993 Sema::CompoundScopeRAII CompoundScope(Actions); 994 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 995 Actions.ActOnStartOfCompoundStmt(); 996 // Parse statement 997 AssociatedStmt = ParseStatement(); 998 Actions.ActOnFinishOfCompoundStmt(); 999 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1000 } 1001 Directive = Actions.ActOnOpenMPExecutableDirective( 1002 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 1003 EndLoc); 1004 1005 // Exit scope. 1006 Actions.EndOpenMPDSABlock(Directive.get()); 1007 OMPDirectiveScope.Exit(); 1008 break; 1009 } 1010 case OMPD_declare_simd: 1011 case OMPD_declare_target: 1012 case OMPD_end_declare_target: 1013 Diag(Tok, diag::err_omp_unexpected_directive) 1014 << getOpenMPDirectiveName(DKind); 1015 SkipUntil(tok::annot_pragma_openmp_end); 1016 break; 1017 case OMPD_unknown: 1018 Diag(Tok, diag::err_omp_unknown_directive); 1019 SkipUntil(tok::annot_pragma_openmp_end); 1020 break; 1021 } 1022 return Directive; 1023} 1024 1025// Parses simple list: 1026// simple-variable-list: 1027// '(' id-expression {, id-expression} ')' 1028// 1029bool Parser::ParseOpenMPSimpleVarList( 1030 OpenMPDirectiveKind Kind, 1031 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 1032 Callback, 1033 bool AllowScopeSpecifier) { 1034 // Parse '('. 1035 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1036 if (T.expectAndConsume(diag::err_expected_lparen_after, 1037 getOpenMPDirectiveName(Kind))) 1038 return true; 1039 bool IsCorrect = true; 1040 bool NoIdentIsFound = true; 1041 1042 // Read tokens while ')' or annot_pragma_openmp_end is not found. 1043 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 1044 CXXScopeSpec SS; 1045 SourceLocation TemplateKWLoc; 1046 UnqualifiedId Name; 1047 // Read var name. 1048 Token PrevTok = Tok; 1049 NoIdentIsFound = false; 1050 1051 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 1052 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) { 1053 IsCorrect = false; 1054 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1055 StopBeforeMatch); 1056 } else if (ParseUnqualifiedId(SS, false, false, false, nullptr, 1057 TemplateKWLoc, Name)) { 1058 IsCorrect = false; 1059 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1060 StopBeforeMatch); 1061 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 1062 Tok.isNot(tok::annot_pragma_openmp_end)) { 1063 IsCorrect = false; 1064 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1065 StopBeforeMatch); 1066 Diag(PrevTok.getLocation(), diag::err_expected) 1067 << tok::identifier 1068 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 1069 } else { 1070 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 1071 } 1072 // Consume ','. 1073 if (Tok.is(tok::comma)) { 1074 ConsumeToken(); 1075 } 1076 } 1077 1078 if (NoIdentIsFound) { 1079 Diag(Tok, diag::err_expected) << tok::identifier; 1080 IsCorrect = false; 1081 } 1082 1083 // Parse ')'. 1084 IsCorrect = !T.consumeClose() && IsCorrect; 1085 1086 return !IsCorrect; 1087} 1088 1089/// \brief Parsing of OpenMP clauses. 1090/// 1091/// clause: 1092/// if-clause | final-clause | num_threads-clause | safelen-clause | 1093/// default-clause | private-clause | firstprivate-clause | shared-clause 1094/// | linear-clause | aligned-clause | collapse-clause | 1095/// lastprivate-clause | reduction-clause | proc_bind-clause | 1096/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 1097/// mergeable-clause | flush-clause | read-clause | write-clause | 1098/// update-clause | capture-clause | seq_cst-clause | device-clause | 1099/// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 1100/// thread_limit-clause | priority-clause | grainsize-clause | 1101/// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 1102/// from-clause | is_device_ptr-clause 1103/// 1104OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 1105 OpenMPClauseKind CKind, bool FirstClause) { 1106 OMPClause *Clause = nullptr; 1107 bool ErrorFound = false; 1108 // Check if clause is allowed for the given directive. 1109 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { 1110 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 1111 << getOpenMPDirectiveName(DKind); 1112 ErrorFound = true; 1113 } 1114 1115 switch (CKind) { 1116 case OMPC_final: 1117 case OMPC_num_threads: 1118 case OMPC_safelen: 1119 case OMPC_simdlen: 1120 case OMPC_collapse: 1121 case OMPC_ordered: 1122 case OMPC_device: 1123 case OMPC_num_teams: 1124 case OMPC_thread_limit: 1125 case OMPC_priority: 1126 case OMPC_grainsize: 1127 case OMPC_num_tasks: 1128 case OMPC_hint: 1129 // OpenMP [2.5, Restrictions] 1130 // At most one num_threads clause can appear on the directive. 1131 // OpenMP [2.8.1, simd construct, Restrictions] 1132 // Only one safelen clause can appear on a simd directive. 1133 // Only one simdlen clause can appear on a simd directive. 1134 // Only one collapse clause can appear on a simd directive. 1135 // OpenMP [2.9.1, target data construct, Restrictions] 1136 // At most one device clause can appear on the directive. 1137 // OpenMP [2.11.1, task Construct, Restrictions] 1138 // At most one if clause can appear on the directive. 1139 // At most one final clause can appear on the directive. 1140 // OpenMP [teams Construct, Restrictions] 1141 // At most one num_teams clause can appear on the directive. 1142 // At most one thread_limit clause can appear on the directive. 1143 // OpenMP [2.9.1, task Construct, Restrictions] 1144 // At most one priority clause can appear on the directive. 1145 // OpenMP [2.9.2, taskloop Construct, Restrictions] 1146 // At most one grainsize clause can appear on the directive. 1147 // OpenMP [2.9.2, taskloop Construct, Restrictions] 1148 // At most one num_tasks clause can appear on the directive. 1149 if (!FirstClause) { 1150 Diag(Tok, diag::err_omp_more_one_clause) 1151 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1152 ErrorFound = true; 1153 } 1154 1155 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 1156 Clause = ParseOpenMPClause(CKind); 1157 else 1158 Clause = ParseOpenMPSingleExprClause(CKind); 1159 break; 1160 case OMPC_default: 1161 case OMPC_proc_bind: 1162 // OpenMP [2.14.3.1, Restrictions] 1163 // Only a single default clause may be specified on a parallel, task or 1164 // teams directive. 1165 // OpenMP [2.5, parallel Construct, Restrictions] 1166 // At most one proc_bind clause can appear on the directive. 1167 if (!FirstClause) { 1168 Diag(Tok, diag::err_omp_more_one_clause) 1169 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1170 ErrorFound = true; 1171 } 1172 1173 Clause = ParseOpenMPSimpleClause(CKind); 1174 break; 1175 case OMPC_schedule: 1176 case OMPC_dist_schedule: 1177 case OMPC_defaultmap: 1178 // OpenMP [2.7.1, Restrictions, p. 3] 1179 // Only one schedule clause can appear on a loop directive. 1180 // OpenMP [2.10.4, Restrictions, p. 106] 1181 // At most one defaultmap clause can appear on the directive. 1182 if (!FirstClause) { 1183 Diag(Tok, diag::err_omp_more_one_clause) 1184 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1185 ErrorFound = true; 1186 } 1187 1188 case OMPC_if: 1189 Clause = ParseOpenMPSingleExprWithArgClause(CKind); 1190 break; 1191 case OMPC_nowait: 1192 case OMPC_untied: 1193 case OMPC_mergeable: 1194 case OMPC_read: 1195 case OMPC_write: 1196 case OMPC_update: 1197 case OMPC_capture: 1198 case OMPC_seq_cst: 1199 case OMPC_threads: 1200 case OMPC_simd: 1201 case OMPC_nogroup: 1202 // OpenMP [2.7.1, Restrictions, p. 9] 1203 // Only one ordered clause can appear on a loop directive. 1204 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 1205 // Only one nowait clause can appear on a for directive. 1206 if (!FirstClause) { 1207 Diag(Tok, diag::err_omp_more_one_clause) 1208 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1209 ErrorFound = true; 1210 } 1211 1212 Clause = ParseOpenMPClause(CKind); 1213 break; 1214 case OMPC_private: 1215 case OMPC_firstprivate: 1216 case OMPC_lastprivate: 1217 case OMPC_shared: 1218 case OMPC_reduction: 1219 case OMPC_linear: 1220 case OMPC_aligned: 1221 case OMPC_copyin: 1222 case OMPC_copyprivate: 1223 case OMPC_flush: 1224 case OMPC_depend: 1225 case OMPC_map: 1226 case OMPC_to: 1227 case OMPC_from: 1228 case OMPC_use_device_ptr: 1229 case OMPC_is_device_ptr: 1230 Clause = ParseOpenMPVarListClause(DKind, CKind); 1231 break; 1232 case OMPC_unknown: 1233 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1234 << getOpenMPDirectiveName(DKind); 1235 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1236 break; 1237 case OMPC_threadprivate: 1238 case OMPC_uniform: 1239 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 1240 << getOpenMPDirectiveName(DKind); 1241 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 1242 break; 1243 } 1244 return ErrorFound ? nullptr : Clause; 1245} 1246 1247/// Parses simple expression in parens for single-expression clauses of OpenMP 1248/// constructs. 1249/// \param RLoc Returned location of right paren. 1250ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 1251 SourceLocation &RLoc) { 1252 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1253 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 1254 return ExprError(); 1255 1256 SourceLocation ELoc = Tok.getLocation(); 1257 ExprResult LHS(ParseCastExpression( 1258 /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); 1259 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 1260 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); 1261 1262 // Parse ')'. 1263 T.consumeClose(); 1264 1265 RLoc = T.getCloseLocation(); 1266 return Val; 1267} 1268 1269/// \brief Parsing of OpenMP clauses with single expressions like 'final', 1270/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 1271/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. 1272/// 1273/// final-clause: 1274/// 'final' '(' expression ')' 1275/// 1276/// num_threads-clause: 1277/// 'num_threads' '(' expression ')' 1278/// 1279/// safelen-clause: 1280/// 'safelen' '(' expression ')' 1281/// 1282/// simdlen-clause: 1283/// 'simdlen' '(' expression ')' 1284/// 1285/// collapse-clause: 1286/// 'collapse' '(' expression ')' 1287/// 1288/// priority-clause: 1289/// 'priority' '(' expression ')' 1290/// 1291/// grainsize-clause: 1292/// 'grainsize' '(' expression ')' 1293/// 1294/// num_tasks-clause: 1295/// 'num_tasks' '(' expression ')' 1296/// 1297/// hint-clause: 1298/// 'hint' '(' expression ')' 1299/// 1300OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { 1301 SourceLocation Loc = ConsumeToken(); 1302 SourceLocation LLoc = Tok.getLocation(); 1303 SourceLocation RLoc; 1304 1305 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 1306 1307 if (Val.isInvalid()) 1308 return nullptr; 1309 1310 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 1311} 1312 1313/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1314/// 1315/// default-clause: 1316/// 'default' '(' 'none' | 'shared' ') 1317/// 1318/// proc_bind-clause: 1319/// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1320/// 1321OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { 1322 SourceLocation Loc = Tok.getLocation(); 1323 SourceLocation LOpen = ConsumeToken(); 1324 // Parse '('. 1325 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1326 if (T.expectAndConsume(diag::err_expected_lparen_after, 1327 getOpenMPClauseName(Kind))) 1328 return nullptr; 1329 1330 unsigned Type = getOpenMPSimpleClauseType( 1331 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1332 SourceLocation TypeLoc = Tok.getLocation(); 1333 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1334 Tok.isNot(tok::annot_pragma_openmp_end)) 1335 ConsumeAnyToken(); 1336 1337 // Parse ')'. 1338 T.consumeClose(); 1339 1340 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, 1341 Tok.getLocation()); 1342} 1343 1344/// \brief Parsing of OpenMP clauses like 'ordered'. 1345/// 1346/// ordered-clause: 1347/// 'ordered' 1348/// 1349/// nowait-clause: 1350/// 'nowait' 1351/// 1352/// untied-clause: 1353/// 'untied' 1354/// 1355/// mergeable-clause: 1356/// 'mergeable' 1357/// 1358/// read-clause: 1359/// 'read' 1360/// 1361/// threads-clause: 1362/// 'threads' 1363/// 1364/// simd-clause: 1365/// 'simd' 1366/// 1367/// nogroup-clause: 1368/// 'nogroup' 1369/// 1370OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { 1371 SourceLocation Loc = Tok.getLocation(); 1372 ConsumeAnyToken(); 1373 1374 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 1375} 1376 1377 1378/// \brief Parsing of OpenMP clauses with single expressions and some additional 1379/// argument like 'schedule' or 'dist_schedule'. 1380/// 1381/// schedule-clause: 1382/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 1383/// ')' 1384/// 1385/// if-clause: 1386/// 'if' '(' [ directive-name-modifier ':' ] expression ')' 1387/// 1388/// defaultmap: 1389/// 'defaultmap' '(' modifier ':' kind ')' 1390/// 1391OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { 1392 SourceLocation Loc = ConsumeToken(); 1393 SourceLocation DelimLoc; 1394 // Parse '('. 1395 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1396 if (T.expectAndConsume(diag::err_expected_lparen_after, 1397 getOpenMPClauseName(Kind))) 1398 return nullptr; 1399 1400 ExprResult Val; 1401 SmallVector<unsigned, 4> Arg; 1402 SmallVector<SourceLocation, 4> KLoc; 1403 if (Kind == OMPC_schedule) { 1404 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 1405 Arg.resize(NumberOfElements); 1406 KLoc.resize(NumberOfElements); 1407 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 1408 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 1409 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 1410 auto KindModifier = getOpenMPSimpleClauseType( 1411 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1412 if (KindModifier > OMPC_SCHEDULE_unknown) { 1413 // Parse 'modifier' 1414 Arg[Modifier1] = KindModifier; 1415 KLoc[Modifier1] = Tok.getLocation(); 1416 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1417 Tok.isNot(tok::annot_pragma_openmp_end)) 1418 ConsumeAnyToken(); 1419 if (Tok.is(tok::comma)) { 1420 // Parse ',' 'modifier' 1421 ConsumeAnyToken(); 1422 KindModifier = getOpenMPSimpleClauseType( 1423 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1424 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 1425 ? KindModifier 1426 : (unsigned)OMPC_SCHEDULE_unknown; 1427 KLoc[Modifier2] = Tok.getLocation(); 1428 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1429 Tok.isNot(tok::annot_pragma_openmp_end)) 1430 ConsumeAnyToken(); 1431 } 1432 // Parse ':' 1433 if (Tok.is(tok::colon)) 1434 ConsumeAnyToken(); 1435 else 1436 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 1437 KindModifier = getOpenMPSimpleClauseType( 1438 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1439 } 1440 Arg[ScheduleKind] = KindModifier; 1441 KLoc[ScheduleKind] = Tok.getLocation(); 1442 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1443 Tok.isNot(tok::annot_pragma_openmp_end)) 1444 ConsumeAnyToken(); 1445 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 1446 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 1447 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 1448 Tok.is(tok::comma)) 1449 DelimLoc = ConsumeAnyToken(); 1450 } else if (Kind == OMPC_dist_schedule) { 1451 Arg.push_back(getOpenMPSimpleClauseType( 1452 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1453 KLoc.push_back(Tok.getLocation()); 1454 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1455 Tok.isNot(tok::annot_pragma_openmp_end)) 1456 ConsumeAnyToken(); 1457 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 1458 DelimLoc = ConsumeAnyToken(); 1459 } else if (Kind == OMPC_defaultmap) { 1460 // Get a defaultmap modifier 1461 Arg.push_back(getOpenMPSimpleClauseType( 1462 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1463 KLoc.push_back(Tok.getLocation()); 1464 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1465 Tok.isNot(tok::annot_pragma_openmp_end)) 1466 ConsumeAnyToken(); 1467 // Parse ':' 1468 if (Tok.is(tok::colon)) 1469 ConsumeAnyToken(); 1470 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 1471 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 1472 // Get a defaultmap kind 1473 Arg.push_back(getOpenMPSimpleClauseType( 1474 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1475 KLoc.push_back(Tok.getLocation()); 1476 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1477 Tok.isNot(tok::annot_pragma_openmp_end)) 1478 ConsumeAnyToken(); 1479 } else { 1480 assert(Kind == OMPC_if); 1481 KLoc.push_back(Tok.getLocation()); 1482 TentativeParsingAction TPA(*this); 1483 Arg.push_back(ParseOpenMPDirectiveKind(*this)); 1484 if (Arg.back() != OMPD_unknown) { 1485 ConsumeToken(); 1486 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 1487 TPA.Commit(); 1488 DelimLoc = ConsumeToken(); 1489 } else { 1490 TPA.Revert(); 1491 Arg.back() = OMPD_unknown; 1492 } 1493 } else 1494 TPA.Revert(); 1495 } 1496 1497 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 1498 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 1499 Kind == OMPC_if; 1500 if (NeedAnExpression) { 1501 SourceLocation ELoc = Tok.getLocation(); 1502 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); 1503 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 1504 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); 1505 } 1506 1507 // Parse ')'. 1508 T.consumeClose(); 1509 1510 if (NeedAnExpression && Val.isInvalid()) 1511 return nullptr; 1512 1513 return Actions.ActOnOpenMPSingleExprWithArgClause( 1514 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, 1515 T.getCloseLocation()); 1516} 1517 1518static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 1519 UnqualifiedId &ReductionId) { 1520 SourceLocation TemplateKWLoc; 1521 if (ReductionIdScopeSpec.isEmpty()) { 1522 auto OOK = OO_None; 1523 switch (P.getCurToken().getKind()) { 1524 case tok::plus: 1525 OOK = OO_Plus; 1526 break; 1527 case tok::minus: 1528 OOK = OO_Minus; 1529 break; 1530 case tok::star: 1531 OOK = OO_Star; 1532 break; 1533 case tok::amp: 1534 OOK = OO_Amp; 1535 break; 1536 case tok::pipe: 1537 OOK = OO_Pipe; 1538 break; 1539 case tok::caret: 1540 OOK = OO_Caret; 1541 break; 1542 case tok::ampamp: 1543 OOK = OO_AmpAmp; 1544 break; 1545 case tok::pipepipe: 1546 OOK = OO_PipePipe; 1547 break; 1548 default: 1549 break; 1550 } 1551 if (OOK != OO_None) { 1552 SourceLocation OpLoc = P.ConsumeToken(); 1553 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 1554 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 1555 return false; 1556 } 1557 } 1558 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, 1559 /*AllowDestructorName*/ false, 1560 /*AllowConstructorName*/ false, nullptr, 1561 TemplateKWLoc, ReductionId); 1562} 1563 1564/// Parses clauses with list. 1565bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 1566 OpenMPClauseKind Kind, 1567 SmallVectorImpl<Expr *> &Vars, 1568 OpenMPVarListDataTy &Data) { 1569 UnqualifiedId UnqualifiedReductionId; 1570 bool InvalidReductionId = false; 1571 bool MapTypeModifierSpecified = false; 1572 1573 // Parse '('. 1574 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1575 if (T.expectAndConsume(diag::err_expected_lparen_after, 1576 getOpenMPClauseName(Kind))) 1577 return true; 1578 1579 bool NeedRParenForLinear = false; 1580 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 1581 tok::annot_pragma_openmp_end); 1582 // Handle reduction-identifier for reduction clause. 1583 if (Kind == OMPC_reduction) { 1584 ColonProtectionRAIIObject ColonRAII(*this); 1585 if (getLangOpts().CPlusPlus) 1586 ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec, 1587 /*ObjectType=*/nullptr, 1588 /*EnteringContext=*/false); 1589 InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec, 1590 UnqualifiedReductionId); 1591 if (InvalidReductionId) { 1592 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 1593 StopBeforeMatch); 1594 } 1595 if (Tok.is(tok::colon)) 1596 Data.ColonLoc = ConsumeToken(); 1597 else 1598 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 1599 if (!InvalidReductionId) 1600 Data.ReductionId = 1601 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 1602 } else if (Kind == OMPC_depend) { 1603 // Handle dependency type for depend clause. 1604 ColonProtectionRAIIObject ColonRAII(*this); 1605 Data.DepKind = 1606 static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( 1607 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); 1608 Data.DepLinMapLoc = Tok.getLocation(); 1609 1610 if (Data.DepKind == OMPC_DEPEND_unknown) { 1611 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 1612 StopBeforeMatch); 1613 } else { 1614 ConsumeToken(); 1615 // Special processing for depend(source) clause. 1616 if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) { 1617 // Parse ')'. 1618 T.consumeClose(); 1619 return false; 1620 } 1621 } 1622 if (Tok.is(tok::colon)) 1623 Data.ColonLoc = ConsumeToken(); 1624 else { 1625 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 1626 : diag::warn_pragma_expected_colon) 1627 << "dependency type"; 1628 } 1629 } else if (Kind == OMPC_linear) { 1630 // Try to parse modifier if any. 1631 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 1632 Data.LinKind = static_cast<OpenMPLinearClauseKind>( 1633 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 1634 Data.DepLinMapLoc = ConsumeToken(); 1635 LinearT.consumeOpen(); 1636 NeedRParenForLinear = true; 1637 } 1638 } else if (Kind == OMPC_map) { 1639 // Handle map type for map clause. 1640 ColonProtectionRAIIObject ColonRAII(*this); 1641 1642 /// The map clause modifier token can be either a identifier or the C++ 1643 /// delete keyword. 1644 auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool { 1645 return Tok.isOneOf(tok::identifier, tok::kw_delete); 1646 }; 1647 1648 // The first identifier may be a list item, a map-type or a 1649 // map-type-modifier. The map modifier can also be delete which has the same 1650 // spelling of the C++ delete keyword. 1651 Data.MapType = 1652 IsMapClauseModifierToken(Tok) 1653 ? static_cast<OpenMPMapClauseKind>( 1654 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) 1655 : OMPC_MAP_unknown; 1656 Data.DepLinMapLoc = Tok.getLocation(); 1657 bool ColonExpected = false; 1658 1659 if (IsMapClauseModifierToken(Tok)) { 1660 if (PP.LookAhead(0).is(tok::colon)) { 1661 if (Data.MapType == OMPC_MAP_unknown) 1662 Diag(Tok, diag::err_omp_unknown_map_type); 1663 else if (Data.MapType == OMPC_MAP_always) 1664 Diag(Tok, diag::err_omp_map_type_missing); 1665 ConsumeToken(); 1666 } else if (PP.LookAhead(0).is(tok::comma)) { 1667 if (IsMapClauseModifierToken(PP.LookAhead(1)) && 1668 PP.LookAhead(2).is(tok::colon)) { 1669 Data.MapTypeModifier = Data.MapType; 1670 if (Data.MapTypeModifier != OMPC_MAP_always) { 1671 Diag(Tok, diag::err_omp_unknown_map_type_modifier); 1672 Data.MapTypeModifier = OMPC_MAP_unknown; 1673 } else 1674 MapTypeModifierSpecified = true; 1675 1676 ConsumeToken(); 1677 ConsumeToken(); 1678 1679 Data.MapType = 1680 IsMapClauseModifierToken(Tok) 1681 ? static_cast<OpenMPMapClauseKind>( 1682 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) 1683 : OMPC_MAP_unknown; 1684 if (Data.MapType == OMPC_MAP_unknown || 1685 Data.MapType == OMPC_MAP_always) 1686 Diag(Tok, diag::err_omp_unknown_map_type); 1687 ConsumeToken(); 1688 } else { 1689 Data.MapType = OMPC_MAP_tofrom; 1690 Data.IsMapTypeImplicit = true; 1691 } 1692 } else { 1693 Data.MapType = OMPC_MAP_tofrom; 1694 Data.IsMapTypeImplicit = true; 1695 } 1696 } else { 1697 Data.MapType = OMPC_MAP_tofrom; 1698 Data.IsMapTypeImplicit = true; 1699 } 1700 1701 if (Tok.is(tok::colon)) 1702 Data.ColonLoc = ConsumeToken(); 1703 else if (ColonExpected) 1704 Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; 1705 } 1706 1707 bool IsComma = 1708 (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 1709 (Kind == OMPC_reduction && !InvalidReductionId) || 1710 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && 1711 (!MapTypeModifierSpecified || 1712 Data.MapTypeModifier == OMPC_MAP_always)) || 1713 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); 1714 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 1715 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 1716 Tok.isNot(tok::annot_pragma_openmp_end))) { 1717 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 1718 // Parse variable 1719 ExprResult VarExpr = 1720 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 1721 if (VarExpr.isUsable()) 1722 Vars.push_back(VarExpr.get()); 1723 else { 1724 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1725 StopBeforeMatch); 1726 } 1727 // Skip ',' if any 1728 IsComma = Tok.is(tok::comma); 1729 if (IsComma) 1730 ConsumeToken(); 1731 else if (Tok.isNot(tok::r_paren) && 1732 Tok.isNot(tok::annot_pragma_openmp_end) && 1733 (!MayHaveTail || Tok.isNot(tok::colon))) 1734 Diag(Tok, diag::err_omp_expected_punc) 1735 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 1736 : getOpenMPClauseName(Kind)) 1737 << (Kind == OMPC_flush); 1738 } 1739 1740 // Parse ')' for linear clause with modifier. 1741 if (NeedRParenForLinear) 1742 LinearT.consumeClose(); 1743 1744 // Parse ':' linear-step (or ':' alignment). 1745 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 1746 if (MustHaveTail) { 1747 Data.ColonLoc = Tok.getLocation(); 1748 SourceLocation ELoc = ConsumeToken(); 1749 ExprResult Tail = ParseAssignmentExpression(); 1750 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); 1751 if (Tail.isUsable()) 1752 Data.TailExpr = Tail.get(); 1753 else 1754 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1755 StopBeforeMatch); 1756 } 1757 1758 // Parse ')'. 1759 T.consumeClose(); 1760 if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && 1761 Vars.empty()) || 1762 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 1763 (MustHaveTail && !Data.TailExpr) || InvalidReductionId) 1764 return true; 1765 return false; 1766} 1767 1768/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 1769/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'. 1770/// 1771/// private-clause: 1772/// 'private' '(' list ')' 1773/// firstprivate-clause: 1774/// 'firstprivate' '(' list ')' 1775/// lastprivate-clause: 1776/// 'lastprivate' '(' list ')' 1777/// shared-clause: 1778/// 'shared' '(' list ')' 1779/// linear-clause: 1780/// 'linear' '(' linear-list [ ':' linear-step ] ')' 1781/// aligned-clause: 1782/// 'aligned' '(' list [ ':' alignment ] ')' 1783/// reduction-clause: 1784/// 'reduction' '(' reduction-identifier ':' list ')' 1785/// copyprivate-clause: 1786/// 'copyprivate' '(' list ')' 1787/// flush-clause: 1788/// 'flush' '(' list ')' 1789/// depend-clause: 1790/// 'depend' '(' in | out | inout : list | source ')' 1791/// map-clause: 1792/// 'map' '(' [ [ always , ] 1793/// to | from | tofrom | alloc | release | delete ':' ] list ')'; 1794/// to-clause: 1795/// 'to' '(' list ')' 1796/// from-clause: 1797/// 'from' '(' list ')' 1798/// use_device_ptr-clause: 1799/// 'use_device_ptr' '(' list ')' 1800/// is_device_ptr-clause: 1801/// 'is_device_ptr' '(' list ')' 1802/// 1803/// For 'linear' clause linear-list may have the following forms: 1804/// list 1805/// modifier(list) 1806/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 1807OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 1808 OpenMPClauseKind Kind) { 1809 SourceLocation Loc = Tok.getLocation(); 1810 SourceLocation LOpen = ConsumeToken(); 1811 SmallVector<Expr *, 4> Vars; 1812 OpenMPVarListDataTy Data; 1813 1814 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 1815 return nullptr; 1816 1817 return Actions.ActOnOpenMPVarListClause( 1818 Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(), 1819 Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind, 1820 Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit, 1821 Data.DepLinMapLoc); 1822} 1823 1824