1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// This file implements parsing of all OpenMP directives and clauses. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/StmtOpenMP.h" 16 #include "clang/Parse/ParseDiagnostic.h" 17 #include "clang/Parse/Parser.h" 18 #include "clang/Parse/RAIIObjectsForParser.h" 19 #include "clang/Sema/Scope.h" 20 #include "llvm/ADT/PointerIntPair.h" 21 22 using namespace clang; 23 24 //===----------------------------------------------------------------------===// 25 // OpenMP declarative directives. 26 //===----------------------------------------------------------------------===// 27 28 namespace { 29 enum OpenMPDirectiveKindEx { 30 OMPD_cancellation = OMPD_unknown + 1, 31 OMPD_data, 32 OMPD_declare, 33 OMPD_end, 34 OMPD_end_declare, 35 OMPD_enter, 36 OMPD_exit, 37 OMPD_point, 38 OMPD_reduction, 39 OMPD_target_enter, 40 OMPD_target_exit, 41 OMPD_update, 42 OMPD_distribute_parallel, 43 OMPD_teams_distribute_parallel, 44 OMPD_target_teams_distribute_parallel 45 }; 46 47 class ThreadprivateListParserHelper final { 48 SmallVector<Expr *, 4> Identifiers; 49 Parser *P; 50 51 public: 52 ThreadprivateListParserHelper(Parser *P) : P(P) {} 53 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 54 ExprResult Res = 55 P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo); 56 if (Res.isUsable()) 57 Identifiers.push_back(Res.get()); 58 } 59 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 60 }; 61 } // namespace 62 63 // Map token string to extended OMP token kind that are 64 // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 65 static unsigned getOpenMPDirectiveKindEx(StringRef S) { 66 auto DKind = getOpenMPDirectiveKind(S); 67 if (DKind != OMPD_unknown) 68 return DKind; 69 70 return llvm::StringSwitch<unsigned>(S) 71 .Case("cancellation", OMPD_cancellation) 72 .Case("data", OMPD_data) 73 .Case("declare", OMPD_declare) 74 .Case("end", OMPD_end) 75 .Case("enter", OMPD_enter) 76 .Case("exit", OMPD_exit) 77 .Case("point", OMPD_point) 78 .Case("reduction", OMPD_reduction) 79 .Case("update", OMPD_update) 80 .Default(OMPD_unknown); 81 } 82 83 static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { 84 // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 85 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 86 // TODO: add other combined directives in topological order. 87 static const unsigned F[][3] = { 88 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 89 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 90 {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 91 {OMPD_declare, OMPD_target, OMPD_declare_target}, 92 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 93 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 94 {OMPD_distribute_parallel_for, OMPD_simd, 95 OMPD_distribute_parallel_for_simd}, 96 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 97 {OMPD_end, OMPD_declare, OMPD_end_declare}, 98 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 99 {OMPD_target, OMPD_data, OMPD_target_data}, 100 {OMPD_target, OMPD_enter, OMPD_target_enter}, 101 {OMPD_target, OMPD_exit, OMPD_target_exit}, 102 {OMPD_target, OMPD_update, OMPD_target_update}, 103 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 104 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 105 {OMPD_for, OMPD_simd, OMPD_for_simd}, 106 {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 107 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 108 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 109 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 110 {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 111 {OMPD_target, OMPD_simd, OMPD_target_simd}, 112 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 113 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 114 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 115 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 116 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 117 {OMPD_teams_distribute_parallel, OMPD_for, 118 OMPD_teams_distribute_parallel_for}, 119 {OMPD_teams_distribute_parallel_for, OMPD_simd, 120 OMPD_teams_distribute_parallel_for_simd}, 121 {OMPD_target, OMPD_teams, OMPD_target_teams}, 122 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 123 {OMPD_target_teams_distribute, OMPD_parallel, 124 OMPD_target_teams_distribute_parallel}, 125 {OMPD_target_teams_distribute, OMPD_simd, 126 OMPD_target_teams_distribute_simd}, 127 {OMPD_target_teams_distribute_parallel, OMPD_for, 128 OMPD_target_teams_distribute_parallel_for}, 129 {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 130 OMPD_target_teams_distribute_parallel_for_simd}}; 131 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 132 Token Tok = P.getCurToken(); 133 unsigned DKind = 134 Tok.isAnnotation() 135 ? static_cast<unsigned>(OMPD_unknown) 136 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 137 if (DKind == OMPD_unknown) 138 return OMPD_unknown; 139 140 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { 141 if (DKind != F[I][0]) 142 continue; 143 144 Tok = P.getPreprocessor().LookAhead(0); 145 unsigned SDKind = 146 Tok.isAnnotation() 147 ? static_cast<unsigned>(OMPD_unknown) 148 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 149 if (SDKind == OMPD_unknown) 150 continue; 151 152 if (SDKind == F[I][1]) { 153 P.ConsumeToken(); 154 DKind = F[I][2]; 155 } 156 } 157 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind) 158 : OMPD_unknown; 159 } 160 161 static DeclarationName parseOpenMPReductionId(Parser &P) { 162 Token Tok = P.getCurToken(); 163 Sema &Actions = P.getActions(); 164 OverloadedOperatorKind OOK = OO_None; 165 // Allow to use 'operator' keyword for C++ operators 166 bool WithOperator = false; 167 if (Tok.is(tok::kw_operator)) { 168 P.ConsumeToken(); 169 Tok = P.getCurToken(); 170 WithOperator = true; 171 } 172 switch (Tok.getKind()) { 173 case tok::plus: // '+' 174 OOK = OO_Plus; 175 break; 176 case tok::minus: // '-' 177 OOK = OO_Minus; 178 break; 179 case tok::star: // '*' 180 OOK = OO_Star; 181 break; 182 case tok::amp: // '&' 183 OOK = OO_Amp; 184 break; 185 case tok::pipe: // '|' 186 OOK = OO_Pipe; 187 break; 188 case tok::caret: // '^' 189 OOK = OO_Caret; 190 break; 191 case tok::ampamp: // '&&' 192 OOK = OO_AmpAmp; 193 break; 194 case tok::pipepipe: // '||' 195 OOK = OO_PipePipe; 196 break; 197 case tok::identifier: // identifier 198 if (!WithOperator) 199 break; 200 LLVM_FALLTHROUGH; 201 default: 202 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 203 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 204 Parser::StopBeforeMatch); 205 return DeclarationName(); 206 } 207 P.ConsumeToken(); 208 auto &DeclNames = Actions.getASTContext().DeclarationNames; 209 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 210 : DeclNames.getCXXOperatorName(OOK); 211 } 212 213 /// Parse 'omp declare reduction' construct. 214 /// 215 /// declare-reduction-directive: 216 /// annot_pragma_openmp 'declare' 'reduction' 217 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 218 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 219 /// annot_pragma_openmp_end 220 /// <reduction_id> is either a base language identifier or one of the following 221 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 222 /// 223 Parser::DeclGroupPtrTy 224 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 225 // Parse '('. 226 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 227 if (T.expectAndConsume(diag::err_expected_lparen_after, 228 getOpenMPDirectiveName(OMPD_declare_reduction))) { 229 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 230 return DeclGroupPtrTy(); 231 } 232 233 DeclarationName Name = parseOpenMPReductionId(*this); 234 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 235 return DeclGroupPtrTy(); 236 237 // Consume ':'. 238 bool IsCorrect = !ExpectAndConsume(tok::colon); 239 240 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 241 return DeclGroupPtrTy(); 242 243 IsCorrect = IsCorrect && !Name.isEmpty(); 244 245 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 246 Diag(Tok.getLocation(), diag::err_expected_type); 247 IsCorrect = false; 248 } 249 250 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 251 return DeclGroupPtrTy(); 252 253 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 254 // Parse list of types until ':' token. 255 do { 256 ColonProtectionRAIIObject ColonRAII(*this); 257 SourceRange Range; 258 TypeResult TR = 259 ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS); 260 if (TR.isUsable()) { 261 QualType ReductionType = 262 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 263 if (!ReductionType.isNull()) { 264 ReductionTypes.push_back( 265 std::make_pair(ReductionType, Range.getBegin())); 266 } 267 } else { 268 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 269 StopBeforeMatch); 270 } 271 272 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 273 break; 274 275 // Consume ','. 276 if (ExpectAndConsume(tok::comma)) { 277 IsCorrect = false; 278 if (Tok.is(tok::annot_pragma_openmp_end)) { 279 Diag(Tok.getLocation(), diag::err_expected_type); 280 return DeclGroupPtrTy(); 281 } 282 } 283 } while (Tok.isNot(tok::annot_pragma_openmp_end)); 284 285 if (ReductionTypes.empty()) { 286 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 287 return DeclGroupPtrTy(); 288 } 289 290 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 291 return DeclGroupPtrTy(); 292 293 // Consume ':'. 294 if (ExpectAndConsume(tok::colon)) 295 IsCorrect = false; 296 297 if (Tok.is(tok::annot_pragma_openmp_end)) { 298 Diag(Tok.getLocation(), diag::err_expected_expression); 299 return DeclGroupPtrTy(); 300 } 301 302 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 303 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 304 305 // Parse <combiner> expression and then parse initializer if any for each 306 // correct type. 307 unsigned I = 0, E = ReductionTypes.size(); 308 for (Decl *D : DRD.get()) { 309 TentativeParsingAction TPA(*this); 310 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 311 Scope::CompoundStmtScope | 312 Scope::OpenMPDirectiveScope); 313 // Parse <combiner> expression. 314 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 315 ExprResult CombinerResult = 316 Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), 317 D->getLocation(), /*DiscardedValue=*/true); 318 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 319 320 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 321 Tok.isNot(tok::annot_pragma_openmp_end)) { 322 TPA.Commit(); 323 IsCorrect = false; 324 break; 325 } 326 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 327 ExprResult InitializerResult; 328 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 329 // Parse <initializer> expression. 330 if (Tok.is(tok::identifier) && 331 Tok.getIdentifierInfo()->isStr("initializer")) { 332 ConsumeToken(); 333 } else { 334 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 335 TPA.Commit(); 336 IsCorrect = false; 337 break; 338 } 339 // Parse '('. 340 BalancedDelimiterTracker T(*this, tok::l_paren, 341 tok::annot_pragma_openmp_end); 342 IsCorrect = 343 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 344 IsCorrect; 345 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 346 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 347 Scope::CompoundStmtScope | 348 Scope::OpenMPDirectiveScope); 349 // Parse expression. 350 VarDecl *OmpPrivParm = 351 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 352 D); 353 // Check if initializer is omp_priv <init_expr> or something else. 354 if (Tok.is(tok::identifier) && 355 Tok.getIdentifierInfo()->isStr("omp_priv")) { 356 if (Actions.getLangOpts().CPlusPlus) { 357 InitializerResult = Actions.ActOnFinishFullExpr( 358 ParseAssignmentExpression().get(), D->getLocation(), 359 /*DiscardedValue=*/true); 360 } else { 361 ConsumeToken(); 362 ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 363 } 364 } else { 365 InitializerResult = Actions.ActOnFinishFullExpr( 366 ParseAssignmentExpression().get(), D->getLocation(), 367 /*DiscardedValue=*/true); 368 } 369 Actions.ActOnOpenMPDeclareReductionInitializerEnd( 370 D, InitializerResult.get(), OmpPrivParm); 371 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 372 Tok.isNot(tok::annot_pragma_openmp_end)) { 373 TPA.Commit(); 374 IsCorrect = false; 375 break; 376 } 377 IsCorrect = 378 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 379 } 380 } 381 382 ++I; 383 // Revert parsing if not the last type, otherwise accept it, we're done with 384 // parsing. 385 if (I != E) 386 TPA.Revert(); 387 else 388 TPA.Commit(); 389 } 390 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 391 IsCorrect); 392 } 393 394 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 395 // Parse declarator '=' initializer. 396 // If a '==' or '+=' is found, suggest a fixit to '='. 397 if (isTokenEqualOrEqualTypo()) { 398 ConsumeToken(); 399 400 if (Tok.is(tok::code_completion)) { 401 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 402 Actions.FinalizeDeclaration(OmpPrivParm); 403 cutOffParsing(); 404 return; 405 } 406 407 ExprResult Init(ParseInitializer()); 408 409 if (Init.isInvalid()) { 410 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 411 Actions.ActOnInitializerError(OmpPrivParm); 412 } else { 413 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 414 /*DirectInit=*/false); 415 } 416 } else if (Tok.is(tok::l_paren)) { 417 // Parse C++ direct initializer: '(' expression-list ')' 418 BalancedDelimiterTracker T(*this, tok::l_paren); 419 T.consumeOpen(); 420 421 ExprVector Exprs; 422 CommaLocsTy CommaLocs; 423 424 SourceLocation LParLoc = T.getOpenLocation(); 425 if (ParseExpressionList( 426 Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] { 427 QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 428 getCurScope(), 429 OmpPrivParm->getType()->getCanonicalTypeInternal(), 430 OmpPrivParm->getLocation(), Exprs, LParLoc); 431 CalledSignatureHelp = true; 432 Actions.CodeCompleteExpression(getCurScope(), PreferredType); 433 })) { 434 if (PP.isCodeCompletionReached() && !CalledSignatureHelp) { 435 Actions.ProduceConstructorSignatureHelp( 436 getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), 437 OmpPrivParm->getLocation(), Exprs, LParLoc); 438 CalledSignatureHelp = true; 439 } 440 Actions.ActOnInitializerError(OmpPrivParm); 441 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 442 } else { 443 // Match the ')'. 444 SourceLocation RLoc = Tok.getLocation(); 445 if (!T.consumeClose()) 446 RLoc = T.getCloseLocation(); 447 448 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && 449 "Unexpected number of commas!"); 450 451 ExprResult Initializer = 452 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); 453 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), 454 /*DirectInit=*/true); 455 } 456 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 457 // Parse C++0x braced-init-list. 458 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 459 460 ExprResult Init(ParseBraceInitializer()); 461 462 if (Init.isInvalid()) { 463 Actions.ActOnInitializerError(OmpPrivParm); 464 } else { 465 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 466 /*DirectInit=*/true); 467 } 468 } else { 469 Actions.ActOnUninitializedDecl(OmpPrivParm); 470 } 471 } 472 473 namespace { 474 /// RAII that recreates function context for correct parsing of clauses of 475 /// 'declare simd' construct. 476 /// OpenMP, 2.8.2 declare simd Construct 477 /// The expressions appearing in the clauses of this directive are evaluated in 478 /// the scope of the arguments of the function declaration or definition. 479 class FNContextRAII final { 480 Parser &P; 481 Sema::CXXThisScopeRAII *ThisScope; 482 Parser::ParseScope *TempScope; 483 Parser::ParseScope *FnScope; 484 bool HasTemplateScope = false; 485 bool HasFunScope = false; 486 FNContextRAII() = delete; 487 FNContextRAII(const FNContextRAII &) = delete; 488 FNContextRAII &operator=(const FNContextRAII &) = delete; 489 490 public: 491 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) { 492 Decl *D = *Ptr.get().begin(); 493 NamedDecl *ND = dyn_cast<NamedDecl>(D); 494 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 495 Sema &Actions = P.getActions(); 496 497 // Allow 'this' within late-parsed attributes. 498 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0, 499 ND && ND->isCXXInstanceMember()); 500 501 // If the Decl is templatized, add template parameters to scope. 502 HasTemplateScope = D->isTemplateDecl(); 503 TempScope = 504 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope); 505 if (HasTemplateScope) 506 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D); 507 508 // If the Decl is on a function, add function parameters to the scope. 509 HasFunScope = D->isFunctionOrFunctionTemplate(); 510 FnScope = new Parser::ParseScope( 511 &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, 512 HasFunScope); 513 if (HasFunScope) 514 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 515 } 516 ~FNContextRAII() { 517 if (HasFunScope) { 518 P.getActions().ActOnExitFunctionContext(); 519 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver 520 } 521 if (HasTemplateScope) 522 TempScope->Exit(); 523 delete FnScope; 524 delete TempScope; 525 delete ThisScope; 526 } 527 }; 528 } // namespace 529 530 /// Parses clauses for 'declare simd' directive. 531 /// clause: 532 /// 'inbranch' | 'notinbranch' 533 /// 'simdlen' '(' <expr> ')' 534 /// { 'uniform' '(' <argument_list> ')' } 535 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 536 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 537 static bool parseDeclareSimdClauses( 538 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 539 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 540 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 541 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 542 SourceRange BSRange; 543 const Token &Tok = P.getCurToken(); 544 bool IsError = false; 545 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 546 if (Tok.isNot(tok::identifier)) 547 break; 548 OMPDeclareSimdDeclAttr::BranchStateTy Out; 549 IdentifierInfo *II = Tok.getIdentifierInfo(); 550 StringRef ClauseName = II->getName(); 551 // Parse 'inranch|notinbranch' clauses. 552 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 553 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 554 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 555 << ClauseName 556 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 557 IsError = true; 558 } 559 BS = Out; 560 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 561 P.ConsumeToken(); 562 } else if (ClauseName.equals("simdlen")) { 563 if (SimdLen.isUsable()) { 564 P.Diag(Tok, diag::err_omp_more_one_clause) 565 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 566 IsError = true; 567 } 568 P.ConsumeToken(); 569 SourceLocation RLoc; 570 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 571 if (SimdLen.isInvalid()) 572 IsError = true; 573 } else { 574 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 575 if (CKind == OMPC_uniform || CKind == OMPC_aligned || 576 CKind == OMPC_linear) { 577 Parser::OpenMPVarListDataTy Data; 578 SmallVectorImpl<Expr *> *Vars = &Uniforms; 579 if (CKind == OMPC_aligned) 580 Vars = &Aligneds; 581 else if (CKind == OMPC_linear) 582 Vars = &Linears; 583 584 P.ConsumeToken(); 585 if (P.ParseOpenMPVarList(OMPD_declare_simd, 586 getOpenMPClauseKind(ClauseName), *Vars, Data)) 587 IsError = true; 588 if (CKind == OMPC_aligned) { 589 Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); 590 } else if (CKind == OMPC_linear) { 591 if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind, 592 Data.DepLinMapLoc)) 593 Data.LinKind = OMPC_LINEAR_val; 594 LinModifiers.append(Linears.size() - LinModifiers.size(), 595 Data.LinKind); 596 Steps.append(Linears.size() - Steps.size(), Data.TailExpr); 597 } 598 } else 599 // TODO: add parsing of other clauses. 600 break; 601 } 602 // Skip ',' if any. 603 if (Tok.is(tok::comma)) 604 P.ConsumeToken(); 605 } 606 return IsError; 607 } 608 609 /// Parse clauses for '#pragma omp declare simd'. 610 Parser::DeclGroupPtrTy 611 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 612 CachedTokens &Toks, SourceLocation Loc) { 613 PP.EnterToken(Tok); 614 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); 615 // Consume the previously pushed token. 616 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 617 618 FNContextRAII FnContext(*this, Ptr); 619 OMPDeclareSimdDeclAttr::BranchStateTy BS = 620 OMPDeclareSimdDeclAttr::BS_Undefined; 621 ExprResult Simdlen; 622 SmallVector<Expr *, 4> Uniforms; 623 SmallVector<Expr *, 4> Aligneds; 624 SmallVector<Expr *, 4> Alignments; 625 SmallVector<Expr *, 4> Linears; 626 SmallVector<unsigned, 4> LinModifiers; 627 SmallVector<Expr *, 4> Steps; 628 bool IsError = 629 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 630 Alignments, Linears, LinModifiers, Steps); 631 // Need to check for extra tokens. 632 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 633 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 634 << getOpenMPDirectiveName(OMPD_declare_simd); 635 while (Tok.isNot(tok::annot_pragma_openmp_end)) 636 ConsumeAnyToken(); 637 } 638 // Skip the last annot_pragma_openmp_end. 639 SourceLocation EndLoc = ConsumeAnnotationToken(); 640 if (IsError) 641 return Ptr; 642 return Actions.ActOnOpenMPDeclareSimdDirective( 643 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 644 LinModifiers, Steps, SourceRange(Loc, EndLoc)); 645 } 646 647 /// Parsing of declarative OpenMP directives. 648 /// 649 /// threadprivate-directive: 650 /// annot_pragma_openmp 'threadprivate' simple-variable-list 651 /// annot_pragma_openmp_end 652 /// 653 /// declare-reduction-directive: 654 /// annot_pragma_openmp 'declare' 'reduction' [...] 655 /// annot_pragma_openmp_end 656 /// 657 /// declare-simd-directive: 658 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 659 /// annot_pragma_openmp_end 660 /// <function declaration/definition> 661 /// 662 /// requires directive: 663 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 664 /// annot_pragma_openmp_end 665 /// 666 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 667 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, 668 DeclSpec::TST TagType, Decl *Tag) { 669 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 670 ParenBraceBracketBalancer BalancerRAIIObj(*this); 671 672 SourceLocation Loc = ConsumeAnnotationToken(); 673 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 674 675 switch (DKind) { 676 case OMPD_threadprivate: { 677 ConsumeToken(); 678 ThreadprivateListParserHelper Helper(this); 679 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) { 680 // The last seen token is annot_pragma_openmp_end - need to check for 681 // extra tokens. 682 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 683 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 684 << getOpenMPDirectiveName(OMPD_threadprivate); 685 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 686 } 687 // Skip the last annot_pragma_openmp_end. 688 ConsumeAnnotationToken(); 689 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 690 Helper.getIdentifiers()); 691 } 692 break; 693 } 694 case OMPD_requires: { 695 SourceLocation StartLoc = ConsumeToken(); 696 SmallVector<OMPClause *, 5> Clauses; 697 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 698 FirstClauses(OMPC_unknown + 1); 699 if (Tok.is(tok::annot_pragma_openmp_end)) { 700 Diag(Tok, diag::err_omp_expected_clause) 701 << getOpenMPDirectiveName(OMPD_requires); 702 break; 703 } 704 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 705 OpenMPClauseKind CKind = Tok.isAnnotation() 706 ? OMPC_unknown 707 : getOpenMPClauseKind(PP.getSpelling(Tok)); 708 Actions.StartOpenMPClause(CKind); 709 OMPClause *Clause = 710 ParseOpenMPClause(OMPD_requires, CKind, !FirstClauses[CKind].getInt()); 711 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, StopBeforeMatch); 712 FirstClauses[CKind].setInt(true); 713 if (Clause != nullptr) 714 Clauses.push_back(Clause); 715 if (Tok.is(tok::annot_pragma_openmp_end)) { 716 Actions.EndOpenMPClause(); 717 break; 718 } 719 // Skip ',' if any. 720 if (Tok.is(tok::comma)) 721 ConsumeToken(); 722 Actions.EndOpenMPClause(); 723 } 724 // Consume final annot_pragma_openmp_end 725 if (Clauses.size() == 0) { 726 Diag(Tok, diag::err_omp_expected_clause) 727 << getOpenMPDirectiveName(OMPD_requires); 728 ConsumeAnnotationToken(); 729 return nullptr; 730 } 731 ConsumeAnnotationToken(); 732 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 733 } 734 case OMPD_declare_reduction: 735 ConsumeToken(); 736 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 737 // The last seen token is annot_pragma_openmp_end - need to check for 738 // extra tokens. 739 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 740 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 741 << getOpenMPDirectiveName(OMPD_declare_reduction); 742 while (Tok.isNot(tok::annot_pragma_openmp_end)) 743 ConsumeAnyToken(); 744 } 745 // Skip the last annot_pragma_openmp_end. 746 ConsumeAnnotationToken(); 747 return Res; 748 } 749 break; 750 case OMPD_declare_simd: { 751 // The syntax is: 752 // { #pragma omp declare simd } 753 // <function-declaration-or-definition> 754 // 755 ConsumeToken(); 756 CachedTokens Toks; 757 while(Tok.isNot(tok::annot_pragma_openmp_end)) { 758 Toks.push_back(Tok); 759 ConsumeAnyToken(); 760 } 761 Toks.push_back(Tok); 762 ConsumeAnyToken(); 763 764 DeclGroupPtrTy Ptr; 765 if (Tok.is(tok::annot_pragma_openmp)) { 766 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); 767 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 768 // Here we expect to see some function declaration. 769 if (AS == AS_none) { 770 assert(TagType == DeclSpec::TST_unspecified); 771 MaybeParseCXX11Attributes(Attrs); 772 ParsingDeclSpec PDS(*this); 773 Ptr = ParseExternalDeclaration(Attrs, &PDS); 774 } else { 775 Ptr = 776 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 777 } 778 } 779 if (!Ptr) { 780 Diag(Loc, diag::err_omp_decl_in_declare_simd); 781 return DeclGroupPtrTy(); 782 } 783 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 784 } 785 case OMPD_declare_target: { 786 SourceLocation DTLoc = ConsumeAnyToken(); 787 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 788 // OpenMP 4.5 syntax with list of entities. 789 Sema::NamedDeclSetType SameDirectiveDecls; 790 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 791 OMPDeclareTargetDeclAttr::MapTypeTy MT = 792 OMPDeclareTargetDeclAttr::MT_To; 793 if (Tok.is(tok::identifier)) { 794 IdentifierInfo *II = Tok.getIdentifierInfo(); 795 StringRef ClauseName = II->getName(); 796 // Parse 'to|link' clauses. 797 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, 798 MT)) { 799 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 800 << ClauseName; 801 break; 802 } 803 ConsumeToken(); 804 } 805 auto &&Callback = [this, MT, &SameDirectiveDecls]( 806 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 807 Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, 808 SameDirectiveDecls); 809 }; 810 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 811 /*AllowScopeSpecifier=*/true)) 812 break; 813 814 // Consume optional ','. 815 if (Tok.is(tok::comma)) 816 ConsumeToken(); 817 } 818 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 819 ConsumeAnyToken(); 820 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), 821 SameDirectiveDecls.end()); 822 if (Decls.empty()) 823 return DeclGroupPtrTy(); 824 return Actions.BuildDeclaratorGroup(Decls); 825 } 826 827 // Skip the last annot_pragma_openmp_end. 828 ConsumeAnyToken(); 829 830 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 831 return DeclGroupPtrTy(); 832 833 llvm::SmallVector<Decl *, 4> Decls; 834 DKind = parseOpenMPDirectiveKind(*this); 835 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && 836 Tok.isNot(tok::r_brace)) { 837 DeclGroupPtrTy Ptr; 838 // Here we expect to see some function declaration. 839 if (AS == AS_none) { 840 assert(TagType == DeclSpec::TST_unspecified); 841 MaybeParseCXX11Attributes(Attrs); 842 ParsingDeclSpec PDS(*this); 843 Ptr = ParseExternalDeclaration(Attrs, &PDS); 844 } else { 845 Ptr = 846 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 847 } 848 if (Ptr) { 849 DeclGroupRef Ref = Ptr.get(); 850 Decls.append(Ref.begin(), Ref.end()); 851 } 852 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 853 TentativeParsingAction TPA(*this); 854 ConsumeAnnotationToken(); 855 DKind = parseOpenMPDirectiveKind(*this); 856 if (DKind != OMPD_end_declare_target) 857 TPA.Revert(); 858 else 859 TPA.Commit(); 860 } 861 } 862 863 if (DKind == OMPD_end_declare_target) { 864 ConsumeAnyToken(); 865 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 866 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 867 << getOpenMPDirectiveName(OMPD_end_declare_target); 868 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 869 } 870 // Skip the last annot_pragma_openmp_end. 871 ConsumeAnyToken(); 872 } else { 873 Diag(Tok, diag::err_expected_end_declare_target); 874 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; 875 } 876 Actions.ActOnFinishOpenMPDeclareTargetDirective(); 877 return Actions.BuildDeclaratorGroup(Decls); 878 } 879 case OMPD_unknown: 880 Diag(Tok, diag::err_omp_unknown_directive); 881 break; 882 case OMPD_parallel: 883 case OMPD_simd: 884 case OMPD_task: 885 case OMPD_taskyield: 886 case OMPD_barrier: 887 case OMPD_taskwait: 888 case OMPD_taskgroup: 889 case OMPD_flush: 890 case OMPD_for: 891 case OMPD_for_simd: 892 case OMPD_sections: 893 case OMPD_section: 894 case OMPD_single: 895 case OMPD_master: 896 case OMPD_ordered: 897 case OMPD_critical: 898 case OMPD_parallel_for: 899 case OMPD_parallel_for_simd: 900 case OMPD_parallel_sections: 901 case OMPD_atomic: 902 case OMPD_target: 903 case OMPD_teams: 904 case OMPD_cancellation_point: 905 case OMPD_cancel: 906 case OMPD_target_data: 907 case OMPD_target_enter_data: 908 case OMPD_target_exit_data: 909 case OMPD_target_parallel: 910 case OMPD_target_parallel_for: 911 case OMPD_taskloop: 912 case OMPD_taskloop_simd: 913 case OMPD_distribute: 914 case OMPD_end_declare_target: 915 case OMPD_target_update: 916 case OMPD_distribute_parallel_for: 917 case OMPD_distribute_parallel_for_simd: 918 case OMPD_distribute_simd: 919 case OMPD_target_parallel_for_simd: 920 case OMPD_target_simd: 921 case OMPD_teams_distribute: 922 case OMPD_teams_distribute_simd: 923 case OMPD_teams_distribute_parallel_for_simd: 924 case OMPD_teams_distribute_parallel_for: 925 case OMPD_target_teams: 926 case OMPD_target_teams_distribute: 927 case OMPD_target_teams_distribute_parallel_for: 928 case OMPD_target_teams_distribute_parallel_for_simd: 929 case OMPD_target_teams_distribute_simd: 930 Diag(Tok, diag::err_omp_unexpected_directive) 931 << 1 << getOpenMPDirectiveName(DKind); 932 break; 933 } 934 while (Tok.isNot(tok::annot_pragma_openmp_end)) 935 ConsumeAnyToken(); 936 ConsumeAnyToken(); 937 return nullptr; 938 } 939 940 /// Parsing of declarative or executable OpenMP directives. 941 /// 942 /// threadprivate-directive: 943 /// annot_pragma_openmp 'threadprivate' simple-variable-list 944 /// annot_pragma_openmp_end 945 /// 946 /// declare-reduction-directive: 947 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 948 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 949 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 950 /// annot_pragma_openmp_end 951 /// 952 /// executable-directive: 953 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 954 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 955 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | 956 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | 957 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' | 958 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 959 /// 'distribute' | 'target enter data' | 'target exit data' | 960 /// 'target parallel' | 'target parallel for' | 961 /// 'target update' | 'distribute parallel for' | 962 /// 'distribute paralle for simd' | 'distribute simd' | 963 /// 'target parallel for simd' | 'target simd' | 964 /// 'teams distribute' | 'teams distribute simd' | 965 /// 'teams distribute parallel for simd' | 966 /// 'teams distribute parallel for' | 'target teams' | 967 /// 'target teams distribute' | 968 /// 'target teams distribute parallel for' | 969 /// 'target teams distribute parallel for simd' | 970 /// 'target teams distribute simd' {clause} 971 /// annot_pragma_openmp_end 972 /// 973 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( 974 AllowedConstructsKind Allowed) { 975 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 976 ParenBraceBracketBalancer BalancerRAIIObj(*this); 977 SmallVector<OMPClause *, 5> Clauses; 978 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 979 FirstClauses(OMPC_unknown + 1); 980 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 981 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 982 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; 983 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 984 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 985 // Name of critical directive. 986 DeclarationNameInfo DirName; 987 StmtResult Directive = StmtError(); 988 bool HasAssociatedStatement = true; 989 bool FlushHasClause = false; 990 991 switch (DKind) { 992 case OMPD_threadprivate: { 993 if (Allowed != ACK_Any) { 994 Diag(Tok, diag::err_omp_immediate_directive) 995 << getOpenMPDirectiveName(DKind) << 0; 996 } 997 ConsumeToken(); 998 ThreadprivateListParserHelper Helper(this); 999 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) { 1000 // The last seen token is annot_pragma_openmp_end - need to check for 1001 // extra tokens. 1002 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1003 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1004 << getOpenMPDirectiveName(OMPD_threadprivate); 1005 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1006 } 1007 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 1008 Loc, Helper.getIdentifiers()); 1009 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1010 } 1011 SkipUntil(tok::annot_pragma_openmp_end); 1012 break; 1013 } 1014 case OMPD_declare_reduction: 1015 ConsumeToken(); 1016 if (DeclGroupPtrTy Res = 1017 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 1018 // The last seen token is annot_pragma_openmp_end - need to check for 1019 // extra tokens. 1020 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1021 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1022 << getOpenMPDirectiveName(OMPD_declare_reduction); 1023 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1024 ConsumeAnyToken(); 1025 } 1026 ConsumeAnyToken(); 1027 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1028 } else { 1029 SkipUntil(tok::annot_pragma_openmp_end); 1030 } 1031 break; 1032 case OMPD_flush: 1033 if (PP.LookAhead(0).is(tok::l_paren)) { 1034 FlushHasClause = true; 1035 // Push copy of the current token back to stream to properly parse 1036 // pseudo-clause OMPFlushClause. 1037 PP.EnterToken(Tok); 1038 } 1039 LLVM_FALLTHROUGH; 1040 case OMPD_taskyield: 1041 case OMPD_barrier: 1042 case OMPD_taskwait: 1043 case OMPD_cancellation_point: 1044 case OMPD_cancel: 1045 case OMPD_target_enter_data: 1046 case OMPD_target_exit_data: 1047 case OMPD_target_update: 1048 if (Allowed == ACK_StatementsOpenMPNonStandalone) { 1049 Diag(Tok, diag::err_omp_immediate_directive) 1050 << getOpenMPDirectiveName(DKind) << 0; 1051 } 1052 HasAssociatedStatement = false; 1053 // Fall through for further analysis. 1054 LLVM_FALLTHROUGH; 1055 case OMPD_parallel: 1056 case OMPD_simd: 1057 case OMPD_for: 1058 case OMPD_for_simd: 1059 case OMPD_sections: 1060 case OMPD_single: 1061 case OMPD_section: 1062 case OMPD_master: 1063 case OMPD_critical: 1064 case OMPD_parallel_for: 1065 case OMPD_parallel_for_simd: 1066 case OMPD_parallel_sections: 1067 case OMPD_task: 1068 case OMPD_ordered: 1069 case OMPD_atomic: 1070 case OMPD_target: 1071 case OMPD_teams: 1072 case OMPD_taskgroup: 1073 case OMPD_target_data: 1074 case OMPD_target_parallel: 1075 case OMPD_target_parallel_for: 1076 case OMPD_taskloop: 1077 case OMPD_taskloop_simd: 1078 case OMPD_distribute: 1079 case OMPD_distribute_parallel_for: 1080 case OMPD_distribute_parallel_for_simd: 1081 case OMPD_distribute_simd: 1082 case OMPD_target_parallel_for_simd: 1083 case OMPD_target_simd: 1084 case OMPD_teams_distribute: 1085 case OMPD_teams_distribute_simd: 1086 case OMPD_teams_distribute_parallel_for_simd: 1087 case OMPD_teams_distribute_parallel_for: 1088 case OMPD_target_teams: 1089 case OMPD_target_teams_distribute: 1090 case OMPD_target_teams_distribute_parallel_for: 1091 case OMPD_target_teams_distribute_parallel_for_simd: 1092 case OMPD_target_teams_distribute_simd: { 1093 ConsumeToken(); 1094 // Parse directive name of the 'critical' directive if any. 1095 if (DKind == OMPD_critical) { 1096 BalancedDelimiterTracker T(*this, tok::l_paren, 1097 tok::annot_pragma_openmp_end); 1098 if (!T.consumeOpen()) { 1099 if (Tok.isAnyIdentifier()) { 1100 DirName = 1101 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 1102 ConsumeAnyToken(); 1103 } else { 1104 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 1105 } 1106 T.consumeClose(); 1107 } 1108 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 1109 CancelRegion = parseOpenMPDirectiveKind(*this); 1110 if (Tok.isNot(tok::annot_pragma_openmp_end)) 1111 ConsumeToken(); 1112 } 1113 1114 if (isOpenMPLoopDirective(DKind)) 1115 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 1116 if (isOpenMPSimdDirective(DKind)) 1117 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 1118 ParseScope OMPDirectiveScope(this, ScopeFlags); 1119 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 1120 1121 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1122 OpenMPClauseKind CKind = 1123 Tok.isAnnotation() 1124 ? OMPC_unknown 1125 : FlushHasClause ? OMPC_flush 1126 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1127 Actions.StartOpenMPClause(CKind); 1128 FlushHasClause = false; 1129 OMPClause *Clause = 1130 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); 1131 FirstClauses[CKind].setInt(true); 1132 if (Clause) { 1133 FirstClauses[CKind].setPointer(Clause); 1134 Clauses.push_back(Clause); 1135 } 1136 1137 // Skip ',' if any. 1138 if (Tok.is(tok::comma)) 1139 ConsumeToken(); 1140 Actions.EndOpenMPClause(); 1141 } 1142 // End location of the directive. 1143 EndLoc = Tok.getLocation(); 1144 // Consume final annot_pragma_openmp_end. 1145 ConsumeAnnotationToken(); 1146 1147 // OpenMP [2.13.8, ordered Construct, Syntax] 1148 // If the depend clause is specified, the ordered construct is a stand-alone 1149 // directive. 1150 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { 1151 if (Allowed == ACK_StatementsOpenMPNonStandalone) { 1152 Diag(Loc, diag::err_omp_immediate_directive) 1153 << getOpenMPDirectiveName(DKind) << 1 1154 << getOpenMPClauseName(OMPC_depend); 1155 } 1156 HasAssociatedStatement = false; 1157 } 1158 1159 StmtResult AssociatedStmt; 1160 if (HasAssociatedStatement) { 1161 // The body is a block scope like in Lambdas and Blocks. 1162 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1163 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 1164 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 1165 // should have at least one compound statement scope within it. 1166 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 1167 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1168 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 1169 DKind == OMPD_target_exit_data) { 1170 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1171 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 1172 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 1173 /*isStmtExpr=*/false)); 1174 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1175 } 1176 Directive = Actions.ActOnOpenMPExecutableDirective( 1177 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 1178 EndLoc); 1179 1180 // Exit scope. 1181 Actions.EndOpenMPDSABlock(Directive.get()); 1182 OMPDirectiveScope.Exit(); 1183 break; 1184 } 1185 case OMPD_declare_simd: 1186 case OMPD_declare_target: 1187 case OMPD_end_declare_target: 1188 case OMPD_requires: 1189 Diag(Tok, diag::err_omp_unexpected_directive) 1190 << 1 << getOpenMPDirectiveName(DKind); 1191 SkipUntil(tok::annot_pragma_openmp_end); 1192 break; 1193 case OMPD_unknown: 1194 Diag(Tok, diag::err_omp_unknown_directive); 1195 SkipUntil(tok::annot_pragma_openmp_end); 1196 break; 1197 } 1198 return Directive; 1199 } 1200 1201 // Parses simple list: 1202 // simple-variable-list: 1203 // '(' id-expression {, id-expression} ')' 1204 // 1205 bool Parser::ParseOpenMPSimpleVarList( 1206 OpenMPDirectiveKind Kind, 1207 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 1208 Callback, 1209 bool AllowScopeSpecifier) { 1210 // Parse '('. 1211 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1212 if (T.expectAndConsume(diag::err_expected_lparen_after, 1213 getOpenMPDirectiveName(Kind))) 1214 return true; 1215 bool IsCorrect = true; 1216 bool NoIdentIsFound = true; 1217 1218 // Read tokens while ')' or annot_pragma_openmp_end is not found. 1219 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 1220 CXXScopeSpec SS; 1221 UnqualifiedId Name; 1222 // Read var name. 1223 Token PrevTok = Tok; 1224 NoIdentIsFound = false; 1225 1226 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 1227 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) { 1228 IsCorrect = false; 1229 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1230 StopBeforeMatch); 1231 } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, 1232 nullptr, Name)) { 1233 IsCorrect = false; 1234 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1235 StopBeforeMatch); 1236 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 1237 Tok.isNot(tok::annot_pragma_openmp_end)) { 1238 IsCorrect = false; 1239 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1240 StopBeforeMatch); 1241 Diag(PrevTok.getLocation(), diag::err_expected) 1242 << tok::identifier 1243 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 1244 } else { 1245 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 1246 } 1247 // Consume ','. 1248 if (Tok.is(tok::comma)) { 1249 ConsumeToken(); 1250 } 1251 } 1252 1253 if (NoIdentIsFound) { 1254 Diag(Tok, diag::err_expected) << tok::identifier; 1255 IsCorrect = false; 1256 } 1257 1258 // Parse ')'. 1259 IsCorrect = !T.consumeClose() && IsCorrect; 1260 1261 return !IsCorrect; 1262 } 1263 1264 /// Parsing of OpenMP clauses. 1265 /// 1266 /// clause: 1267 /// if-clause | final-clause | num_threads-clause | safelen-clause | 1268 /// default-clause | private-clause | firstprivate-clause | shared-clause 1269 /// | linear-clause | aligned-clause | collapse-clause | 1270 /// lastprivate-clause | reduction-clause | proc_bind-clause | 1271 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 1272 /// mergeable-clause | flush-clause | read-clause | write-clause | 1273 /// update-clause | capture-clause | seq_cst-clause | device-clause | 1274 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 1275 /// thread_limit-clause | priority-clause | grainsize-clause | 1276 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 1277 /// from-clause | is_device_ptr-clause | task_reduction-clause | 1278 /// in_reduction-clause 1279 /// 1280 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 1281 OpenMPClauseKind CKind, bool FirstClause) { 1282 OMPClause *Clause = nullptr; 1283 bool ErrorFound = false; 1284 bool WrongDirective = false; 1285 // Check if clause is allowed for the given directive. 1286 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { 1287 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 1288 << getOpenMPDirectiveName(DKind); 1289 ErrorFound = true; 1290 WrongDirective = true; 1291 } 1292 1293 switch (CKind) { 1294 case OMPC_final: 1295 case OMPC_num_threads: 1296 case OMPC_safelen: 1297 case OMPC_simdlen: 1298 case OMPC_collapse: 1299 case OMPC_ordered: 1300 case OMPC_device: 1301 case OMPC_num_teams: 1302 case OMPC_thread_limit: 1303 case OMPC_priority: 1304 case OMPC_grainsize: 1305 case OMPC_num_tasks: 1306 case OMPC_hint: 1307 // OpenMP [2.5, Restrictions] 1308 // At most one num_threads clause can appear on the directive. 1309 // OpenMP [2.8.1, simd construct, Restrictions] 1310 // Only one safelen clause can appear on a simd directive. 1311 // Only one simdlen clause can appear on a simd directive. 1312 // Only one collapse clause can appear on a simd directive. 1313 // OpenMP [2.9.1, target data construct, Restrictions] 1314 // At most one device clause can appear on the directive. 1315 // OpenMP [2.11.1, task Construct, Restrictions] 1316 // At most one if clause can appear on the directive. 1317 // At most one final clause can appear on the directive. 1318 // OpenMP [teams Construct, Restrictions] 1319 // At most one num_teams clause can appear on the directive. 1320 // At most one thread_limit clause can appear on the directive. 1321 // OpenMP [2.9.1, task Construct, Restrictions] 1322 // At most one priority clause can appear on the directive. 1323 // OpenMP [2.9.2, taskloop Construct, Restrictions] 1324 // At most one grainsize clause can appear on the directive. 1325 // OpenMP [2.9.2, taskloop Construct, Restrictions] 1326 // At most one num_tasks clause can appear on the directive. 1327 if (!FirstClause) { 1328 Diag(Tok, diag::err_omp_more_one_clause) 1329 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1330 ErrorFound = true; 1331 } 1332 1333 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 1334 Clause = ParseOpenMPClause(CKind, WrongDirective); 1335 else 1336 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 1337 break; 1338 case OMPC_default: 1339 case OMPC_proc_bind: 1340 case OMPC_atomic_default_mem_order: 1341 // OpenMP [2.14.3.1, Restrictions] 1342 // Only a single default clause may be specified on a parallel, task or 1343 // teams directive. 1344 // OpenMP [2.5, parallel Construct, Restrictions] 1345 // At most one proc_bind clause can appear on the directive. 1346 // OpenMP [5.0, Requires directive, Restrictions] 1347 // At most one atomic_default_mem_order clause can appear 1348 // on the directive 1349 if (!FirstClause) { 1350 Diag(Tok, diag::err_omp_more_one_clause) 1351 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1352 ErrorFound = true; 1353 } 1354 1355 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 1356 break; 1357 case OMPC_schedule: 1358 case OMPC_dist_schedule: 1359 case OMPC_defaultmap: 1360 // OpenMP [2.7.1, Restrictions, p. 3] 1361 // Only one schedule clause can appear on a loop directive. 1362 // OpenMP [2.10.4, Restrictions, p. 106] 1363 // At most one defaultmap clause can appear on the directive. 1364 if (!FirstClause) { 1365 Diag(Tok, diag::err_omp_more_one_clause) 1366 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1367 ErrorFound = true; 1368 } 1369 LLVM_FALLTHROUGH; 1370 1371 case OMPC_if: 1372 Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); 1373 break; 1374 case OMPC_nowait: 1375 case OMPC_untied: 1376 case OMPC_mergeable: 1377 case OMPC_read: 1378 case OMPC_write: 1379 case OMPC_update: 1380 case OMPC_capture: 1381 case OMPC_seq_cst: 1382 case OMPC_threads: 1383 case OMPC_simd: 1384 case OMPC_nogroup: 1385 case OMPC_unified_address: 1386 case OMPC_unified_shared_memory: 1387 case OMPC_reverse_offload: 1388 case OMPC_dynamic_allocators: 1389 // OpenMP [2.7.1, Restrictions, p. 9] 1390 // Only one ordered clause can appear on a loop directive. 1391 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 1392 // Only one nowait clause can appear on a for directive. 1393 // OpenMP [5.0, Requires directive, Restrictions] 1394 // Each of the requires clauses can appear at most once on the directive. 1395 if (!FirstClause) { 1396 Diag(Tok, diag::err_omp_more_one_clause) 1397 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1398 ErrorFound = true; 1399 } 1400 1401 Clause = ParseOpenMPClause(CKind, WrongDirective); 1402 break; 1403 case OMPC_private: 1404 case OMPC_firstprivate: 1405 case OMPC_lastprivate: 1406 case OMPC_shared: 1407 case OMPC_reduction: 1408 case OMPC_task_reduction: 1409 case OMPC_in_reduction: 1410 case OMPC_linear: 1411 case OMPC_aligned: 1412 case OMPC_copyin: 1413 case OMPC_copyprivate: 1414 case OMPC_flush: 1415 case OMPC_depend: 1416 case OMPC_map: 1417 case OMPC_to: 1418 case OMPC_from: 1419 case OMPC_use_device_ptr: 1420 case OMPC_is_device_ptr: 1421 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 1422 break; 1423 case OMPC_unknown: 1424 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1425 << getOpenMPDirectiveName(DKind); 1426 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1427 break; 1428 case OMPC_threadprivate: 1429 case OMPC_uniform: 1430 if (!WrongDirective) 1431 Diag(Tok, diag::err_omp_unexpected_clause) 1432 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 1433 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 1434 break; 1435 } 1436 return ErrorFound ? nullptr : Clause; 1437 } 1438 1439 /// Parses simple expression in parens for single-expression clauses of OpenMP 1440 /// constructs. 1441 /// \param RLoc Returned location of right paren. 1442 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 1443 SourceLocation &RLoc) { 1444 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1445 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 1446 return ExprError(); 1447 1448 SourceLocation ELoc = Tok.getLocation(); 1449 ExprResult LHS(ParseCastExpression( 1450 /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); 1451 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 1452 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); 1453 1454 // Parse ')'. 1455 RLoc = Tok.getLocation(); 1456 if (!T.consumeClose()) 1457 RLoc = T.getCloseLocation(); 1458 1459 return Val; 1460 } 1461 1462 /// Parsing of OpenMP clauses with single expressions like 'final', 1463 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 1464 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. 1465 /// 1466 /// final-clause: 1467 /// 'final' '(' expression ')' 1468 /// 1469 /// num_threads-clause: 1470 /// 'num_threads' '(' expression ')' 1471 /// 1472 /// safelen-clause: 1473 /// 'safelen' '(' expression ')' 1474 /// 1475 /// simdlen-clause: 1476 /// 'simdlen' '(' expression ')' 1477 /// 1478 /// collapse-clause: 1479 /// 'collapse' '(' expression ')' 1480 /// 1481 /// priority-clause: 1482 /// 'priority' '(' expression ')' 1483 /// 1484 /// grainsize-clause: 1485 /// 'grainsize' '(' expression ')' 1486 /// 1487 /// num_tasks-clause: 1488 /// 'num_tasks' '(' expression ')' 1489 /// 1490 /// hint-clause: 1491 /// 'hint' '(' expression ')' 1492 /// 1493 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 1494 bool ParseOnly) { 1495 SourceLocation Loc = ConsumeToken(); 1496 SourceLocation LLoc = Tok.getLocation(); 1497 SourceLocation RLoc; 1498 1499 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 1500 1501 if (Val.isInvalid()) 1502 return nullptr; 1503 1504 if (ParseOnly) 1505 return nullptr; 1506 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 1507 } 1508 1509 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1510 /// 1511 /// default-clause: 1512 /// 'default' '(' 'none' | 'shared' ') 1513 /// 1514 /// proc_bind-clause: 1515 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1516 /// 1517 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 1518 bool ParseOnly) { 1519 SourceLocation Loc = Tok.getLocation(); 1520 SourceLocation LOpen = ConsumeToken(); 1521 // Parse '('. 1522 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1523 if (T.expectAndConsume(diag::err_expected_lparen_after, 1524 getOpenMPClauseName(Kind))) 1525 return nullptr; 1526 1527 unsigned Type = getOpenMPSimpleClauseType( 1528 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1529 SourceLocation TypeLoc = Tok.getLocation(); 1530 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1531 Tok.isNot(tok::annot_pragma_openmp_end)) 1532 ConsumeAnyToken(); 1533 1534 // Parse ')'. 1535 SourceLocation RLoc = Tok.getLocation(); 1536 if (!T.consumeClose()) 1537 RLoc = T.getCloseLocation(); 1538 1539 if (ParseOnly) 1540 return nullptr; 1541 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc); 1542 } 1543 1544 /// Parsing of OpenMP clauses like 'ordered'. 1545 /// 1546 /// ordered-clause: 1547 /// 'ordered' 1548 /// 1549 /// nowait-clause: 1550 /// 'nowait' 1551 /// 1552 /// untied-clause: 1553 /// 'untied' 1554 /// 1555 /// mergeable-clause: 1556 /// 'mergeable' 1557 /// 1558 /// read-clause: 1559 /// 'read' 1560 /// 1561 /// threads-clause: 1562 /// 'threads' 1563 /// 1564 /// simd-clause: 1565 /// 'simd' 1566 /// 1567 /// nogroup-clause: 1568 /// 'nogroup' 1569 /// 1570 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 1571 SourceLocation Loc = Tok.getLocation(); 1572 ConsumeAnyToken(); 1573 1574 if (ParseOnly) 1575 return nullptr; 1576 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 1577 } 1578 1579 1580 /// Parsing of OpenMP clauses with single expressions and some additional 1581 /// argument like 'schedule' or 'dist_schedule'. 1582 /// 1583 /// schedule-clause: 1584 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 1585 /// ')' 1586 /// 1587 /// if-clause: 1588 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 1589 /// 1590 /// defaultmap: 1591 /// 'defaultmap' '(' modifier ':' kind ')' 1592 /// 1593 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, 1594 bool ParseOnly) { 1595 SourceLocation Loc = ConsumeToken(); 1596 SourceLocation DelimLoc; 1597 // Parse '('. 1598 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1599 if (T.expectAndConsume(diag::err_expected_lparen_after, 1600 getOpenMPClauseName(Kind))) 1601 return nullptr; 1602 1603 ExprResult Val; 1604 SmallVector<unsigned, 4> Arg; 1605 SmallVector<SourceLocation, 4> KLoc; 1606 if (Kind == OMPC_schedule) { 1607 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 1608 Arg.resize(NumberOfElements); 1609 KLoc.resize(NumberOfElements); 1610 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 1611 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 1612 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 1613 unsigned KindModifier = getOpenMPSimpleClauseType( 1614 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1615 if (KindModifier > OMPC_SCHEDULE_unknown) { 1616 // Parse 'modifier' 1617 Arg[Modifier1] = KindModifier; 1618 KLoc[Modifier1] = Tok.getLocation(); 1619 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1620 Tok.isNot(tok::annot_pragma_openmp_end)) 1621 ConsumeAnyToken(); 1622 if (Tok.is(tok::comma)) { 1623 // Parse ',' 'modifier' 1624 ConsumeAnyToken(); 1625 KindModifier = getOpenMPSimpleClauseType( 1626 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1627 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 1628 ? KindModifier 1629 : (unsigned)OMPC_SCHEDULE_unknown; 1630 KLoc[Modifier2] = Tok.getLocation(); 1631 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1632 Tok.isNot(tok::annot_pragma_openmp_end)) 1633 ConsumeAnyToken(); 1634 } 1635 // Parse ':' 1636 if (Tok.is(tok::colon)) 1637 ConsumeAnyToken(); 1638 else 1639 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 1640 KindModifier = getOpenMPSimpleClauseType( 1641 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1642 } 1643 Arg[ScheduleKind] = KindModifier; 1644 KLoc[ScheduleKind] = Tok.getLocation(); 1645 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1646 Tok.isNot(tok::annot_pragma_openmp_end)) 1647 ConsumeAnyToken(); 1648 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 1649 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 1650 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 1651 Tok.is(tok::comma)) 1652 DelimLoc = ConsumeAnyToken(); 1653 } else if (Kind == OMPC_dist_schedule) { 1654 Arg.push_back(getOpenMPSimpleClauseType( 1655 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1656 KLoc.push_back(Tok.getLocation()); 1657 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1658 Tok.isNot(tok::annot_pragma_openmp_end)) 1659 ConsumeAnyToken(); 1660 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 1661 DelimLoc = ConsumeAnyToken(); 1662 } else if (Kind == OMPC_defaultmap) { 1663 // Get a defaultmap modifier 1664 Arg.push_back(getOpenMPSimpleClauseType( 1665 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1666 KLoc.push_back(Tok.getLocation()); 1667 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1668 Tok.isNot(tok::annot_pragma_openmp_end)) 1669 ConsumeAnyToken(); 1670 // Parse ':' 1671 if (Tok.is(tok::colon)) 1672 ConsumeAnyToken(); 1673 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 1674 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 1675 // Get a defaultmap kind 1676 Arg.push_back(getOpenMPSimpleClauseType( 1677 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1678 KLoc.push_back(Tok.getLocation()); 1679 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1680 Tok.isNot(tok::annot_pragma_openmp_end)) 1681 ConsumeAnyToken(); 1682 } else { 1683 assert(Kind == OMPC_if); 1684 KLoc.push_back(Tok.getLocation()); 1685 TentativeParsingAction TPA(*this); 1686 Arg.push_back(parseOpenMPDirectiveKind(*this)); 1687 if (Arg.back() != OMPD_unknown) { 1688 ConsumeToken(); 1689 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 1690 TPA.Commit(); 1691 DelimLoc = ConsumeToken(); 1692 } else { 1693 TPA.Revert(); 1694 Arg.back() = OMPD_unknown; 1695 } 1696 } else { 1697 TPA.Revert(); 1698 } 1699 } 1700 1701 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 1702 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 1703 Kind == OMPC_if; 1704 if (NeedAnExpression) { 1705 SourceLocation ELoc = Tok.getLocation(); 1706 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); 1707 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 1708 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); 1709 } 1710 1711 // Parse ')'. 1712 SourceLocation RLoc = Tok.getLocation(); 1713 if (!T.consumeClose()) 1714 RLoc = T.getCloseLocation(); 1715 1716 if (NeedAnExpression && Val.isInvalid()) 1717 return nullptr; 1718 1719 if (ParseOnly) 1720 return nullptr; 1721 return Actions.ActOnOpenMPSingleExprWithArgClause( 1722 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 1723 } 1724 1725 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 1726 UnqualifiedId &ReductionId) { 1727 if (ReductionIdScopeSpec.isEmpty()) { 1728 auto OOK = OO_None; 1729 switch (P.getCurToken().getKind()) { 1730 case tok::plus: 1731 OOK = OO_Plus; 1732 break; 1733 case tok::minus: 1734 OOK = OO_Minus; 1735 break; 1736 case tok::star: 1737 OOK = OO_Star; 1738 break; 1739 case tok::amp: 1740 OOK = OO_Amp; 1741 break; 1742 case tok::pipe: 1743 OOK = OO_Pipe; 1744 break; 1745 case tok::caret: 1746 OOK = OO_Caret; 1747 break; 1748 case tok::ampamp: 1749 OOK = OO_AmpAmp; 1750 break; 1751 case tok::pipepipe: 1752 OOK = OO_PipePipe; 1753 break; 1754 default: 1755 break; 1756 } 1757 if (OOK != OO_None) { 1758 SourceLocation OpLoc = P.ConsumeToken(); 1759 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 1760 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 1761 return false; 1762 } 1763 } 1764 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, 1765 /*AllowDestructorName*/ false, 1766 /*AllowConstructorName*/ false, 1767 /*AllowDeductionGuide*/ false, 1768 nullptr, nullptr, ReductionId); 1769 } 1770 1771 /// Parses clauses with list. 1772 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 1773 OpenMPClauseKind Kind, 1774 SmallVectorImpl<Expr *> &Vars, 1775 OpenMPVarListDataTy &Data) { 1776 UnqualifiedId UnqualifiedReductionId; 1777 bool InvalidReductionId = false; 1778 bool MapTypeModifierSpecified = false; 1779 1780 // Parse '('. 1781 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1782 if (T.expectAndConsume(diag::err_expected_lparen_after, 1783 getOpenMPClauseName(Kind))) 1784 return true; 1785 1786 bool NeedRParenForLinear = false; 1787 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 1788 tok::annot_pragma_openmp_end); 1789 // Handle reduction-identifier for reduction clause. 1790 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 1791 Kind == OMPC_in_reduction) { 1792 ColonProtectionRAIIObject ColonRAII(*this); 1793 if (getLangOpts().CPlusPlus) 1794 ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec, 1795 /*ObjectType=*/nullptr, 1796 /*EnteringContext=*/false); 1797 InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec, 1798 UnqualifiedReductionId); 1799 if (InvalidReductionId) { 1800 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 1801 StopBeforeMatch); 1802 } 1803 if (Tok.is(tok::colon)) 1804 Data.ColonLoc = ConsumeToken(); 1805 else 1806 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 1807 if (!InvalidReductionId) 1808 Data.ReductionId = 1809 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 1810 } else if (Kind == OMPC_depend) { 1811 // Handle dependency type for depend clause. 1812 ColonProtectionRAIIObject ColonRAII(*this); 1813 Data.DepKind = 1814 static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( 1815 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); 1816 Data.DepLinMapLoc = Tok.getLocation(); 1817 1818 if (Data.DepKind == OMPC_DEPEND_unknown) { 1819 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 1820 StopBeforeMatch); 1821 } else { 1822 ConsumeToken(); 1823 // Special processing for depend(source) clause. 1824 if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) { 1825 // Parse ')'. 1826 T.consumeClose(); 1827 return false; 1828 } 1829 } 1830 if (Tok.is(tok::colon)) { 1831 Data.ColonLoc = ConsumeToken(); 1832 } else { 1833 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 1834 : diag::warn_pragma_expected_colon) 1835 << "dependency type"; 1836 } 1837 } else if (Kind == OMPC_linear) { 1838 // Try to parse modifier if any. 1839 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 1840 Data.LinKind = static_cast<OpenMPLinearClauseKind>( 1841 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 1842 Data.DepLinMapLoc = ConsumeToken(); 1843 LinearT.consumeOpen(); 1844 NeedRParenForLinear = true; 1845 } 1846 } else if (Kind == OMPC_map) { 1847 // Handle map type for map clause. 1848 ColonProtectionRAIIObject ColonRAII(*this); 1849 1850 /// The map clause modifier token can be either a identifier or the C++ 1851 /// delete keyword. 1852 auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool { 1853 return Tok.isOneOf(tok::identifier, tok::kw_delete); 1854 }; 1855 1856 // The first identifier may be a list item, a map-type or a 1857 // map-type-modifier. The map modifier can also be delete which has the same 1858 // spelling of the C++ delete keyword. 1859 Data.MapType = 1860 IsMapClauseModifierToken(Tok) 1861 ? static_cast<OpenMPMapClauseKind>( 1862 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) 1863 : OMPC_MAP_unknown; 1864 Data.DepLinMapLoc = Tok.getLocation(); 1865 bool ColonExpected = false; 1866 1867 if (IsMapClauseModifierToken(Tok)) { 1868 if (PP.LookAhead(0).is(tok::colon)) { 1869 if (Data.MapType == OMPC_MAP_unknown) 1870 Diag(Tok, diag::err_omp_unknown_map_type); 1871 else if (Data.MapType == OMPC_MAP_always) 1872 Diag(Tok, diag::err_omp_map_type_missing); 1873 ConsumeToken(); 1874 } else if (PP.LookAhead(0).is(tok::comma)) { 1875 if (IsMapClauseModifierToken(PP.LookAhead(1)) && 1876 PP.LookAhead(2).is(tok::colon)) { 1877 Data.MapTypeModifier = Data.MapType; 1878 if (Data.MapTypeModifier != OMPC_MAP_always) { 1879 Diag(Tok, diag::err_omp_unknown_map_type_modifier); 1880 Data.MapTypeModifier = OMPC_MAP_unknown; 1881 } else { 1882 MapTypeModifierSpecified = true; 1883 } 1884 1885 ConsumeToken(); 1886 ConsumeToken(); 1887 1888 Data.MapType = 1889 IsMapClauseModifierToken(Tok) 1890 ? static_cast<OpenMPMapClauseKind>( 1891 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) 1892 : OMPC_MAP_unknown; 1893 if (Data.MapType == OMPC_MAP_unknown || 1894 Data.MapType == OMPC_MAP_always) 1895 Diag(Tok, diag::err_omp_unknown_map_type); 1896 ConsumeToken(); 1897 } else { 1898 Data.MapType = OMPC_MAP_tofrom; 1899 Data.IsMapTypeImplicit = true; 1900 } 1901 } else if (IsMapClauseModifierToken(PP.LookAhead(0))) { 1902 if (PP.LookAhead(1).is(tok::colon)) { 1903 Data.MapTypeModifier = Data.MapType; 1904 if (Data.MapTypeModifier != OMPC_MAP_always) { 1905 Diag(Tok, diag::err_omp_unknown_map_type_modifier); 1906 Data.MapTypeModifier = OMPC_MAP_unknown; 1907 } else { 1908 MapTypeModifierSpecified = true; 1909 } 1910 1911 ConsumeToken(); 1912 1913 Data.MapType = 1914 IsMapClauseModifierToken(Tok) 1915 ? static_cast<OpenMPMapClauseKind>( 1916 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) 1917 : OMPC_MAP_unknown; 1918 if (Data.MapType == OMPC_MAP_unknown || 1919 Data.MapType == OMPC_MAP_always) 1920 Diag(Tok, diag::err_omp_unknown_map_type); 1921 ConsumeToken(); 1922 } else { 1923 Data.MapType = OMPC_MAP_tofrom; 1924 Data.IsMapTypeImplicit = true; 1925 } 1926 } else { 1927 Data.MapType = OMPC_MAP_tofrom; 1928 Data.IsMapTypeImplicit = true; 1929 } 1930 } else { 1931 Data.MapType = OMPC_MAP_tofrom; 1932 Data.IsMapTypeImplicit = true; 1933 } 1934 1935 if (Tok.is(tok::colon)) 1936 Data.ColonLoc = ConsumeToken(); 1937 else if (ColonExpected) 1938 Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; 1939 } 1940 1941 bool IsComma = 1942 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 1943 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 1944 (Kind == OMPC_reduction && !InvalidReductionId) || 1945 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && 1946 (!MapTypeModifierSpecified || 1947 Data.MapTypeModifier == OMPC_MAP_always)) || 1948 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); 1949 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 1950 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 1951 Tok.isNot(tok::annot_pragma_openmp_end))) { 1952 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 1953 // Parse variable 1954 ExprResult VarExpr = 1955 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 1956 if (VarExpr.isUsable()) { 1957 Vars.push_back(VarExpr.get()); 1958 } else { 1959 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1960 StopBeforeMatch); 1961 } 1962 // Skip ',' if any 1963 IsComma = Tok.is(tok::comma); 1964 if (IsComma) 1965 ConsumeToken(); 1966 else if (Tok.isNot(tok::r_paren) && 1967 Tok.isNot(tok::annot_pragma_openmp_end) && 1968 (!MayHaveTail || Tok.isNot(tok::colon))) 1969 Diag(Tok, diag::err_omp_expected_punc) 1970 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 1971 : getOpenMPClauseName(Kind)) 1972 << (Kind == OMPC_flush); 1973 } 1974 1975 // Parse ')' for linear clause with modifier. 1976 if (NeedRParenForLinear) 1977 LinearT.consumeClose(); 1978 1979 // Parse ':' linear-step (or ':' alignment). 1980 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 1981 if (MustHaveTail) { 1982 Data.ColonLoc = Tok.getLocation(); 1983 SourceLocation ELoc = ConsumeToken(); 1984 ExprResult Tail = ParseAssignmentExpression(); 1985 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); 1986 if (Tail.isUsable()) 1987 Data.TailExpr = Tail.get(); 1988 else 1989 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1990 StopBeforeMatch); 1991 } 1992 1993 // Parse ')'. 1994 Data.RLoc = Tok.getLocation(); 1995 if (!T.consumeClose()) 1996 Data.RLoc = T.getCloseLocation(); 1997 return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && 1998 Vars.empty()) || 1999 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 2000 (MustHaveTail && !Data.TailExpr) || InvalidReductionId; 2001 } 2002 2003 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 2004 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or 2005 /// 'in_reduction'. 2006 /// 2007 /// private-clause: 2008 /// 'private' '(' list ')' 2009 /// firstprivate-clause: 2010 /// 'firstprivate' '(' list ')' 2011 /// lastprivate-clause: 2012 /// 'lastprivate' '(' list ')' 2013 /// shared-clause: 2014 /// 'shared' '(' list ')' 2015 /// linear-clause: 2016 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 2017 /// aligned-clause: 2018 /// 'aligned' '(' list [ ':' alignment ] ')' 2019 /// reduction-clause: 2020 /// 'reduction' '(' reduction-identifier ':' list ')' 2021 /// task_reduction-clause: 2022 /// 'task_reduction' '(' reduction-identifier ':' list ')' 2023 /// in_reduction-clause: 2024 /// 'in_reduction' '(' reduction-identifier ':' list ')' 2025 /// copyprivate-clause: 2026 /// 'copyprivate' '(' list ')' 2027 /// flush-clause: 2028 /// 'flush' '(' list ')' 2029 /// depend-clause: 2030 /// 'depend' '(' in | out | inout : list | source ')' 2031 /// map-clause: 2032 /// 'map' '(' [ [ always , ] 2033 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 2034 /// to-clause: 2035 /// 'to' '(' list ')' 2036 /// from-clause: 2037 /// 'from' '(' list ')' 2038 /// use_device_ptr-clause: 2039 /// 'use_device_ptr' '(' list ')' 2040 /// is_device_ptr-clause: 2041 /// 'is_device_ptr' '(' list ')' 2042 /// 2043 /// For 'linear' clause linear-list may have the following forms: 2044 /// list 2045 /// modifier(list) 2046 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 2047 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 2048 OpenMPClauseKind Kind, 2049 bool ParseOnly) { 2050 SourceLocation Loc = Tok.getLocation(); 2051 SourceLocation LOpen = ConsumeToken(); 2052 SmallVector<Expr *, 4> Vars; 2053 OpenMPVarListDataTy Data; 2054 2055 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 2056 return nullptr; 2057 2058 if (ParseOnly) 2059 return nullptr; 2060 return Actions.ActOnOpenMPVarListClause( 2061 Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc, 2062 Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind, 2063 Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit, 2064 Data.DepLinMapLoc); 2065 } 2066 2067