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