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