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