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