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