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