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