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