1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file implements parsing of all OpenMP directives and clauses. 10 /// 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/ASTContext.h" 14 #include "clang/AST/OpenMPClause.h" 15 #include "clang/AST/StmtOpenMP.h" 16 #include "clang/Basic/OpenMPKinds.h" 17 #include "clang/Basic/TargetInfo.h" 18 #include "clang/Basic/TokenKinds.h" 19 #include "clang/Parse/ParseDiagnostic.h" 20 #include "clang/Parse/Parser.h" 21 #include "clang/Parse/RAIIObjectsForParser.h" 22 #include "clang/Sema/Scope.h" 23 #include "llvm/ADT/PointerIntPair.h" 24 #include "llvm/ADT/UniqueVector.h" 25 #include "llvm/Frontend/OpenMP/OMPContext.h" 26 27 using namespace clang; 28 using namespace llvm::omp; 29 30 //===----------------------------------------------------------------------===// 31 // OpenMP declarative directives. 32 //===----------------------------------------------------------------------===// 33 34 namespace { 35 enum OpenMPDirectiveKindEx { 36 OMPD_cancellation = llvm::omp::Directive_enumSize + 1, 37 OMPD_data, 38 OMPD_declare, 39 OMPD_end, 40 OMPD_end_declare, 41 OMPD_enter, 42 OMPD_exit, 43 OMPD_point, 44 OMPD_reduction, 45 OMPD_target_enter, 46 OMPD_target_exit, 47 OMPD_update, 48 OMPD_distribute_parallel, 49 OMPD_teams_distribute_parallel, 50 OMPD_target_teams_distribute_parallel, 51 OMPD_mapper, 52 OMPD_variant, 53 OMPD_begin, 54 OMPD_begin_declare, 55 }; 56 57 // Helper to unify the enum class OpenMPDirectiveKind with its extension 58 // the OpenMPDirectiveKindEx enum which allows to use them together as if they 59 // are unsigned values. 60 struct OpenMPDirectiveKindExWrapper { 61 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {} 62 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {} 63 bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); } 64 bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); } 65 bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); } 66 operator unsigned() const { return Value; } 67 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); } 68 unsigned Value; 69 }; 70 71 class DeclDirectiveListParserHelper final { 72 SmallVector<Expr *, 4> Identifiers; 73 Parser *P; 74 OpenMPDirectiveKind Kind; 75 76 public: 77 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) 78 : P(P), Kind(Kind) {} 79 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 80 ExprResult Res = P->getActions().ActOnOpenMPIdExpression( 81 P->getCurScope(), SS, NameInfo, Kind); 82 if (Res.isUsable()) 83 Identifiers.push_back(Res.get()); 84 } 85 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 86 }; 87 } // namespace 88 89 // Map token string to extended OMP token kind that are 90 // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 91 static unsigned getOpenMPDirectiveKindEx(StringRef S) { 92 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S); 93 if (DKind != OMPD_unknown) 94 return DKind; 95 96 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S) 97 .Case("cancellation", OMPD_cancellation) 98 .Case("data", OMPD_data) 99 .Case("declare", OMPD_declare) 100 .Case("end", OMPD_end) 101 .Case("enter", OMPD_enter) 102 .Case("exit", OMPD_exit) 103 .Case("point", OMPD_point) 104 .Case("reduction", OMPD_reduction) 105 .Case("update", OMPD_update) 106 .Case("mapper", OMPD_mapper) 107 .Case("variant", OMPD_variant) 108 .Case("begin", OMPD_begin) 109 .Default(OMPD_unknown); 110 } 111 112 static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { 113 // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 114 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 115 // TODO: add other combined directives in topological order. 116 static const OpenMPDirectiveKindExWrapper F[][3] = { 117 {OMPD_begin, OMPD_declare, OMPD_begin_declare}, 118 {OMPD_end, OMPD_declare, OMPD_end_declare}, 119 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 120 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 121 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, 122 {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 123 {OMPD_declare, OMPD_target, OMPD_declare_target}, 124 {OMPD_declare, OMPD_variant, OMPD_declare_variant}, 125 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant}, 126 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant}, 127 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 128 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 129 {OMPD_distribute_parallel_for, OMPD_simd, 130 OMPD_distribute_parallel_for_simd}, 131 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 132 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 133 {OMPD_target, OMPD_data, OMPD_target_data}, 134 {OMPD_target, OMPD_enter, OMPD_target_enter}, 135 {OMPD_target, OMPD_exit, OMPD_target_exit}, 136 {OMPD_target, OMPD_update, OMPD_target_update}, 137 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 138 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 139 {OMPD_for, OMPD_simd, OMPD_for_simd}, 140 {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 141 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 142 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 143 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 144 {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 145 {OMPD_target, OMPD_simd, OMPD_target_simd}, 146 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 147 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 148 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 149 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 150 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 151 {OMPD_teams_distribute_parallel, OMPD_for, 152 OMPD_teams_distribute_parallel_for}, 153 {OMPD_teams_distribute_parallel_for, OMPD_simd, 154 OMPD_teams_distribute_parallel_for_simd}, 155 {OMPD_target, OMPD_teams, OMPD_target_teams}, 156 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 157 {OMPD_target_teams_distribute, OMPD_parallel, 158 OMPD_target_teams_distribute_parallel}, 159 {OMPD_target_teams_distribute, OMPD_simd, 160 OMPD_target_teams_distribute_simd}, 161 {OMPD_target_teams_distribute_parallel, OMPD_for, 162 OMPD_target_teams_distribute_parallel_for}, 163 {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 164 OMPD_target_teams_distribute_parallel_for_simd}, 165 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, 166 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, 167 {OMPD_parallel, OMPD_master, OMPD_parallel_master}, 168 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, 169 {OMPD_parallel_master_taskloop, OMPD_simd, 170 OMPD_parallel_master_taskloop_simd}}; 171 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 172 Token Tok = P.getCurToken(); 173 OpenMPDirectiveKindExWrapper DKind = 174 Tok.isAnnotation() 175 ? static_cast<unsigned>(OMPD_unknown) 176 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 177 if (DKind == OMPD_unknown) 178 return OMPD_unknown; 179 180 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { 181 if (DKind != F[I][0]) 182 continue; 183 184 Tok = P.getPreprocessor().LookAhead(0); 185 OpenMPDirectiveKindExWrapper SDKind = 186 Tok.isAnnotation() 187 ? static_cast<unsigned>(OMPD_unknown) 188 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 189 if (SDKind == OMPD_unknown) 190 continue; 191 192 if (SDKind == F[I][1]) { 193 P.ConsumeToken(); 194 DKind = F[I][2]; 195 } 196 } 197 return unsigned(DKind) < llvm::omp::Directive_enumSize 198 ? static_cast<OpenMPDirectiveKind>(DKind) 199 : OMPD_unknown; 200 } 201 202 static DeclarationName parseOpenMPReductionId(Parser &P) { 203 Token Tok = P.getCurToken(); 204 Sema &Actions = P.getActions(); 205 OverloadedOperatorKind OOK = OO_None; 206 // Allow to use 'operator' keyword for C++ operators 207 bool WithOperator = false; 208 if (Tok.is(tok::kw_operator)) { 209 P.ConsumeToken(); 210 Tok = P.getCurToken(); 211 WithOperator = true; 212 } 213 switch (Tok.getKind()) { 214 case tok::plus: // '+' 215 OOK = OO_Plus; 216 break; 217 case tok::minus: // '-' 218 OOK = OO_Minus; 219 break; 220 case tok::star: // '*' 221 OOK = OO_Star; 222 break; 223 case tok::amp: // '&' 224 OOK = OO_Amp; 225 break; 226 case tok::pipe: // '|' 227 OOK = OO_Pipe; 228 break; 229 case tok::caret: // '^' 230 OOK = OO_Caret; 231 break; 232 case tok::ampamp: // '&&' 233 OOK = OO_AmpAmp; 234 break; 235 case tok::pipepipe: // '||' 236 OOK = OO_PipePipe; 237 break; 238 case tok::identifier: // identifier 239 if (!WithOperator) 240 break; 241 LLVM_FALLTHROUGH; 242 default: 243 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 244 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 245 Parser::StopBeforeMatch); 246 return DeclarationName(); 247 } 248 P.ConsumeToken(); 249 auto &DeclNames = Actions.getASTContext().DeclarationNames; 250 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 251 : DeclNames.getCXXOperatorName(OOK); 252 } 253 254 /// Parse 'omp declare reduction' construct. 255 /// 256 /// declare-reduction-directive: 257 /// annot_pragma_openmp 'declare' 'reduction' 258 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 259 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 260 /// annot_pragma_openmp_end 261 /// <reduction_id> is either a base language identifier or one of the following 262 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 263 /// 264 Parser::DeclGroupPtrTy 265 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 266 // Parse '('. 267 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 268 if (T.expectAndConsume( 269 diag::err_expected_lparen_after, 270 getOpenMPDirectiveName(OMPD_declare_reduction).data())) { 271 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 272 return DeclGroupPtrTy(); 273 } 274 275 DeclarationName Name = parseOpenMPReductionId(*this); 276 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 277 return DeclGroupPtrTy(); 278 279 // Consume ':'. 280 bool IsCorrect = !ExpectAndConsume(tok::colon); 281 282 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 283 return DeclGroupPtrTy(); 284 285 IsCorrect = IsCorrect && !Name.isEmpty(); 286 287 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 288 Diag(Tok.getLocation(), diag::err_expected_type); 289 IsCorrect = false; 290 } 291 292 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 293 return DeclGroupPtrTy(); 294 295 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 296 // Parse list of types until ':' token. 297 do { 298 ColonProtectionRAIIObject ColonRAII(*this); 299 SourceRange Range; 300 TypeResult TR = 301 ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS); 302 if (TR.isUsable()) { 303 QualType ReductionType = 304 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 305 if (!ReductionType.isNull()) { 306 ReductionTypes.push_back( 307 std::make_pair(ReductionType, Range.getBegin())); 308 } 309 } else { 310 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 311 StopBeforeMatch); 312 } 313 314 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 315 break; 316 317 // Consume ','. 318 if (ExpectAndConsume(tok::comma)) { 319 IsCorrect = false; 320 if (Tok.is(tok::annot_pragma_openmp_end)) { 321 Diag(Tok.getLocation(), diag::err_expected_type); 322 return DeclGroupPtrTy(); 323 } 324 } 325 } while (Tok.isNot(tok::annot_pragma_openmp_end)); 326 327 if (ReductionTypes.empty()) { 328 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 329 return DeclGroupPtrTy(); 330 } 331 332 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 333 return DeclGroupPtrTy(); 334 335 // Consume ':'. 336 if (ExpectAndConsume(tok::colon)) 337 IsCorrect = false; 338 339 if (Tok.is(tok::annot_pragma_openmp_end)) { 340 Diag(Tok.getLocation(), diag::err_expected_expression); 341 return DeclGroupPtrTy(); 342 } 343 344 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 345 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 346 347 // Parse <combiner> expression and then parse initializer if any for each 348 // correct type. 349 unsigned I = 0, E = ReductionTypes.size(); 350 for (Decl *D : DRD.get()) { 351 TentativeParsingAction TPA(*this); 352 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 353 Scope::CompoundStmtScope | 354 Scope::OpenMPDirectiveScope); 355 // Parse <combiner> expression. 356 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 357 ExprResult CombinerResult = Actions.ActOnFinishFullExpr( 358 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false); 359 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 360 361 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 362 Tok.isNot(tok::annot_pragma_openmp_end)) { 363 TPA.Commit(); 364 IsCorrect = false; 365 break; 366 } 367 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 368 ExprResult InitializerResult; 369 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 370 // Parse <initializer> expression. 371 if (Tok.is(tok::identifier) && 372 Tok.getIdentifierInfo()->isStr("initializer")) { 373 ConsumeToken(); 374 } else { 375 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 376 TPA.Commit(); 377 IsCorrect = false; 378 break; 379 } 380 // Parse '('. 381 BalancedDelimiterTracker T(*this, tok::l_paren, 382 tok::annot_pragma_openmp_end); 383 IsCorrect = 384 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 385 IsCorrect; 386 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 387 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 388 Scope::CompoundStmtScope | 389 Scope::OpenMPDirectiveScope); 390 // Parse expression. 391 VarDecl *OmpPrivParm = 392 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 393 D); 394 // Check if initializer is omp_priv <init_expr> or something else. 395 if (Tok.is(tok::identifier) && 396 Tok.getIdentifierInfo()->isStr("omp_priv")) { 397 ConsumeToken(); 398 ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 399 } else { 400 InitializerResult = Actions.ActOnFinishFullExpr( 401 ParseAssignmentExpression().get(), D->getLocation(), 402 /*DiscardedValue*/ false); 403 } 404 Actions.ActOnOpenMPDeclareReductionInitializerEnd( 405 D, InitializerResult.get(), OmpPrivParm); 406 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 407 Tok.isNot(tok::annot_pragma_openmp_end)) { 408 TPA.Commit(); 409 IsCorrect = false; 410 break; 411 } 412 IsCorrect = 413 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 414 } 415 } 416 417 ++I; 418 // Revert parsing if not the last type, otherwise accept it, we're done with 419 // parsing. 420 if (I != E) 421 TPA.Revert(); 422 else 423 TPA.Commit(); 424 } 425 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 426 IsCorrect); 427 } 428 429 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 430 // Parse declarator '=' initializer. 431 // If a '==' or '+=' is found, suggest a fixit to '='. 432 if (isTokenEqualOrEqualTypo()) { 433 ConsumeToken(); 434 435 if (Tok.is(tok::code_completion)) { 436 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 437 Actions.FinalizeDeclaration(OmpPrivParm); 438 cutOffParsing(); 439 return; 440 } 441 442 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm); 443 ExprResult Init = ParseInitializer(); 444 445 if (Init.isInvalid()) { 446 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 447 Actions.ActOnInitializerError(OmpPrivParm); 448 } else { 449 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 450 /*DirectInit=*/false); 451 } 452 } else if (Tok.is(tok::l_paren)) { 453 // Parse C++ direct initializer: '(' expression-list ')' 454 BalancedDelimiterTracker T(*this, tok::l_paren); 455 T.consumeOpen(); 456 457 ExprVector Exprs; 458 CommaLocsTy CommaLocs; 459 460 SourceLocation LParLoc = T.getOpenLocation(); 461 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { 462 QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 463 getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), 464 OmpPrivParm->getLocation(), Exprs, LParLoc); 465 CalledSignatureHelp = true; 466 return PreferredType; 467 }; 468 if (ParseExpressionList(Exprs, CommaLocs, [&] { 469 PreferredType.enterFunctionArgument(Tok.getLocation(), 470 RunSignatureHelp); 471 })) { 472 if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 473 RunSignatureHelp(); 474 Actions.ActOnInitializerError(OmpPrivParm); 475 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 476 } else { 477 // Match the ')'. 478 SourceLocation RLoc = Tok.getLocation(); 479 if (!T.consumeClose()) 480 RLoc = T.getCloseLocation(); 481 482 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && 483 "Unexpected number of commas!"); 484 485 ExprResult Initializer = 486 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); 487 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), 488 /*DirectInit=*/true); 489 } 490 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 491 // Parse C++0x braced-init-list. 492 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 493 494 ExprResult Init(ParseBraceInitializer()); 495 496 if (Init.isInvalid()) { 497 Actions.ActOnInitializerError(OmpPrivParm); 498 } else { 499 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 500 /*DirectInit=*/true); 501 } 502 } else { 503 Actions.ActOnUninitializedDecl(OmpPrivParm); 504 } 505 } 506 507 /// Parses 'omp declare mapper' directive. 508 /// 509 /// declare-mapper-directive: 510 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':'] 511 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 512 /// annot_pragma_openmp_end 513 /// <mapper-identifier> and <var> are base language identifiers. 514 /// 515 Parser::DeclGroupPtrTy 516 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { 517 bool IsCorrect = true; 518 // Parse '(' 519 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 520 if (T.expectAndConsume(diag::err_expected_lparen_after, 521 getOpenMPDirectiveName(OMPD_declare_mapper).data())) { 522 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 523 return DeclGroupPtrTy(); 524 } 525 526 // Parse <mapper-identifier> 527 auto &DeclNames = Actions.getASTContext().DeclarationNames; 528 DeclarationName MapperId; 529 if (PP.LookAhead(0).is(tok::colon)) { 530 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 531 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 532 IsCorrect = false; 533 } else { 534 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo()); 535 } 536 ConsumeToken(); 537 // Consume ':'. 538 ExpectAndConsume(tok::colon); 539 } else { 540 // If no mapper identifier is provided, its name is "default" by default 541 MapperId = 542 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default")); 543 } 544 545 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 546 return DeclGroupPtrTy(); 547 548 // Parse <type> <var> 549 DeclarationName VName; 550 QualType MapperType; 551 SourceRange Range; 552 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS); 553 if (ParsedType.isUsable()) 554 MapperType = 555 Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType); 556 if (MapperType.isNull()) 557 IsCorrect = false; 558 if (!IsCorrect) { 559 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 560 return DeclGroupPtrTy(); 561 } 562 563 // Consume ')'. 564 IsCorrect &= !T.consumeClose(); 565 if (!IsCorrect) { 566 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 567 return DeclGroupPtrTy(); 568 } 569 570 // Enter scope. 571 DeclarationNameInfo DirName; 572 SourceLocation Loc = Tok.getLocation(); 573 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 574 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 575 ParseScope OMPDirectiveScope(this, ScopeFlags); 576 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc); 577 578 // Add the mapper variable declaration. 579 ExprResult MapperVarRef = Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl( 580 getCurScope(), MapperType, Range.getBegin(), VName); 581 582 // Parse map clauses. 583 SmallVector<OMPClause *, 6> Clauses; 584 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 585 OpenMPClauseKind CKind = Tok.isAnnotation() 586 ? OMPC_unknown 587 : getOpenMPClauseKind(PP.getSpelling(Tok)); 588 Actions.StartOpenMPClause(CKind); 589 OMPClause *Clause = 590 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty()); 591 if (Clause) 592 Clauses.push_back(Clause); 593 else 594 IsCorrect = false; 595 // Skip ',' if any. 596 if (Tok.is(tok::comma)) 597 ConsumeToken(); 598 Actions.EndOpenMPClause(); 599 } 600 if (Clauses.empty()) { 601 Diag(Tok, diag::err_omp_expected_clause) 602 << getOpenMPDirectiveName(OMPD_declare_mapper); 603 IsCorrect = false; 604 } 605 606 // Exit scope. 607 Actions.EndOpenMPDSABlock(nullptr); 608 OMPDirectiveScope.Exit(); 609 DeclGroupPtrTy DG = Actions.ActOnOpenMPDeclareMapperDirective( 610 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType, 611 Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses); 612 if (!IsCorrect) 613 return DeclGroupPtrTy(); 614 615 return DG; 616 } 617 618 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, 619 DeclarationName &Name, 620 AccessSpecifier AS) { 621 // Parse the common declaration-specifiers piece. 622 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier; 623 DeclSpec DS(AttrFactory); 624 ParseSpecifierQualifierList(DS, AS, DSC); 625 626 // Parse the declarator. 627 DeclaratorContext Context = DeclaratorContext::PrototypeContext; 628 Declarator DeclaratorInfo(DS, Context); 629 ParseDeclarator(DeclaratorInfo); 630 Range = DeclaratorInfo.getSourceRange(); 631 if (DeclaratorInfo.getIdentifier() == nullptr) { 632 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator); 633 return true; 634 } 635 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName(); 636 637 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo); 638 } 639 640 namespace { 641 /// RAII that recreates function context for correct parsing of clauses of 642 /// 'declare simd' construct. 643 /// OpenMP, 2.8.2 declare simd Construct 644 /// The expressions appearing in the clauses of this directive are evaluated in 645 /// the scope of the arguments of the function declaration or definition. 646 class FNContextRAII final { 647 Parser &P; 648 Sema::CXXThisScopeRAII *ThisScope; 649 Parser::MultiParseScope Scopes; 650 bool HasFunScope = false; 651 FNContextRAII() = delete; 652 FNContextRAII(const FNContextRAII &) = delete; 653 FNContextRAII &operator=(const FNContextRAII &) = delete; 654 655 public: 656 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) { 657 Decl *D = *Ptr.get().begin(); 658 NamedDecl *ND = dyn_cast<NamedDecl>(D); 659 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 660 Sema &Actions = P.getActions(); 661 662 // Allow 'this' within late-parsed attributes. 663 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), 664 ND && ND->isCXXInstanceMember()); 665 666 // If the Decl is templatized, add template parameters to scope. 667 // FIXME: Track CurTemplateDepth? 668 P.ReenterTemplateScopes(Scopes, D); 669 670 // If the Decl is on a function, add function parameters to the scope. 671 if (D->isFunctionOrFunctionTemplate()) { 672 HasFunScope = true; 673 Scopes.Enter(Scope::FnScope | Scope::DeclScope | 674 Scope::CompoundStmtScope); 675 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 676 } 677 } 678 ~FNContextRAII() { 679 if (HasFunScope) 680 P.getActions().ActOnExitFunctionContext(); 681 delete ThisScope; 682 } 683 }; 684 } // namespace 685 686 /// Parses clauses for 'declare simd' directive. 687 /// clause: 688 /// 'inbranch' | 'notinbranch' 689 /// 'simdlen' '(' <expr> ')' 690 /// { 'uniform' '(' <argument_list> ')' } 691 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 692 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 693 static bool parseDeclareSimdClauses( 694 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 695 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 696 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 697 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 698 SourceRange BSRange; 699 const Token &Tok = P.getCurToken(); 700 bool IsError = false; 701 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 702 if (Tok.isNot(tok::identifier)) 703 break; 704 OMPDeclareSimdDeclAttr::BranchStateTy Out; 705 IdentifierInfo *II = Tok.getIdentifierInfo(); 706 StringRef ClauseName = II->getName(); 707 // Parse 'inranch|notinbranch' clauses. 708 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 709 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 710 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 711 << ClauseName 712 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 713 IsError = true; 714 } 715 BS = Out; 716 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 717 P.ConsumeToken(); 718 } else if (ClauseName.equals("simdlen")) { 719 if (SimdLen.isUsable()) { 720 P.Diag(Tok, diag::err_omp_more_one_clause) 721 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 722 IsError = true; 723 } 724 P.ConsumeToken(); 725 SourceLocation RLoc; 726 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 727 if (SimdLen.isInvalid()) 728 IsError = true; 729 } else { 730 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 731 if (CKind == OMPC_uniform || CKind == OMPC_aligned || 732 CKind == OMPC_linear) { 733 Parser::OpenMPVarListDataTy Data; 734 SmallVectorImpl<Expr *> *Vars = &Uniforms; 735 if (CKind == OMPC_aligned) { 736 Vars = &Aligneds; 737 } else if (CKind == OMPC_linear) { 738 Data.ExtraModifier = OMPC_LINEAR_val; 739 Vars = &Linears; 740 } 741 742 P.ConsumeToken(); 743 if (P.ParseOpenMPVarList(OMPD_declare_simd, 744 getOpenMPClauseKind(ClauseName), *Vars, Data)) 745 IsError = true; 746 if (CKind == OMPC_aligned) { 747 Alignments.append(Aligneds.size() - Alignments.size(), 748 Data.DepModOrTailExpr); 749 } else if (CKind == OMPC_linear) { 750 assert(0 <= Data.ExtraModifier && 751 Data.ExtraModifier <= OMPC_LINEAR_unknown && 752 "Unexpected linear modifier."); 753 if (P.getActions().CheckOpenMPLinearModifier( 754 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier), 755 Data.ExtraModifierLoc)) 756 Data.ExtraModifier = OMPC_LINEAR_val; 757 LinModifiers.append(Linears.size() - LinModifiers.size(), 758 Data.ExtraModifier); 759 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr); 760 } 761 } else 762 // TODO: add parsing of other clauses. 763 break; 764 } 765 // Skip ',' if any. 766 if (Tok.is(tok::comma)) 767 P.ConsumeToken(); 768 } 769 return IsError; 770 } 771 772 /// Parse clauses for '#pragma omp declare simd'. 773 Parser::DeclGroupPtrTy 774 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 775 CachedTokens &Toks, SourceLocation Loc) { 776 PP.EnterToken(Tok, /*IsReinject*/ true); 777 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 778 /*IsReinject*/ true); 779 // Consume the previously pushed token. 780 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 781 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 782 783 FNContextRAII FnContext(*this, Ptr); 784 OMPDeclareSimdDeclAttr::BranchStateTy BS = 785 OMPDeclareSimdDeclAttr::BS_Undefined; 786 ExprResult Simdlen; 787 SmallVector<Expr *, 4> Uniforms; 788 SmallVector<Expr *, 4> Aligneds; 789 SmallVector<Expr *, 4> Alignments; 790 SmallVector<Expr *, 4> Linears; 791 SmallVector<unsigned, 4> LinModifiers; 792 SmallVector<Expr *, 4> Steps; 793 bool IsError = 794 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 795 Alignments, Linears, LinModifiers, Steps); 796 skipUntilPragmaOpenMPEnd(OMPD_declare_simd); 797 // Skip the last annot_pragma_openmp_end. 798 SourceLocation EndLoc = ConsumeAnnotationToken(); 799 if (IsError) 800 return Ptr; 801 return Actions.ActOnOpenMPDeclareSimdDirective( 802 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 803 LinModifiers, Steps, SourceRange(Loc, EndLoc)); 804 } 805 806 namespace { 807 /// Constant used in the diagnostics to distinguish the levels in an OpenMP 808 /// contexts: selector-set={selector(trait, ...), ...}, .... 809 enum OMPContextLvl { 810 CONTEXT_SELECTOR_SET_LVL = 0, 811 CONTEXT_SELECTOR_LVL = 1, 812 CONTEXT_TRAIT_LVL = 2, 813 }; 814 815 static StringRef stringLiteralParser(Parser &P) { 816 ExprResult Res = P.ParseStringLiteralExpression(true); 817 return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : ""; 818 } 819 820 static StringRef getNameFromIdOrString(Parser &P, Token &Tok, 821 OMPContextLvl Lvl) { 822 if (Tok.is(tok::identifier)) { 823 llvm::SmallString<16> Buffer; 824 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer); 825 (void)P.ConsumeToken(); 826 return Name; 827 } 828 829 if (tok::isStringLiteral(Tok.getKind())) 830 return stringLiteralParser(P); 831 832 P.Diag(Tok.getLocation(), 833 diag::warn_omp_declare_variant_string_literal_or_identifier) 834 << Lvl; 835 return ""; 836 } 837 838 static bool checkForDuplicates(Parser &P, StringRef Name, 839 SourceLocation NameLoc, 840 llvm::StringMap<SourceLocation> &Seen, 841 OMPContextLvl Lvl) { 842 auto Res = Seen.try_emplace(Name, NameLoc); 843 if (Res.second) 844 return false; 845 846 // Each trait-set-selector-name, trait-selector-name and trait-name can 847 // only be specified once. 848 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use) 849 << Lvl << Name; 850 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) 851 << Lvl << Name; 852 return true; 853 } 854 } // namespace 855 856 void Parser::parseOMPTraitPropertyKind( 857 OMPTraitProperty &TIProperty, llvm::omp::TraitSet Set, 858 llvm::omp::TraitSelector Selector, llvm::StringMap<SourceLocation> &Seen) { 859 TIProperty.Kind = TraitProperty::invalid; 860 861 SourceLocation NameLoc = Tok.getLocation(); 862 StringRef Name = 863 getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL); 864 if (Name.empty()) { 865 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 866 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector); 867 return; 868 } 869 870 TIProperty.RawString = Name; 871 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name); 872 if (TIProperty.Kind != TraitProperty::invalid) { 873 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL)) 874 TIProperty.Kind = TraitProperty::invalid; 875 return; 876 } 877 878 // It follows diagnosis and helping notes. 879 // FIXME: We should move the diagnosis string generation into libFrontend. 880 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property) 881 << Name << getOpenMPContextTraitSelectorName(Selector) 882 << getOpenMPContextTraitSetName(Set); 883 884 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 885 if (SetForName != TraitSet::invalid) { 886 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 887 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL; 888 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 889 << Name << "<selector-name>" 890 << "(<property-name>)"; 891 return; 892 } 893 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 894 if (SelectorForName != TraitSelector::invalid) { 895 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 896 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL; 897 bool AllowsTraitScore = false; 898 bool RequiresProperty = false; 899 isValidTraitSelectorForTraitSet( 900 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 901 AllowsTraitScore, RequiresProperty); 902 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 903 << getOpenMPContextTraitSetName( 904 getOpenMPContextTraitSetForSelector(SelectorForName)) 905 << Name << (RequiresProperty ? "(<property-name>)" : ""); 906 return; 907 } 908 for (const auto &PotentialSet : 909 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 910 TraitSet::device}) { 911 TraitProperty PropertyForName = 912 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name); 913 if (PropertyForName == TraitProperty::invalid) 914 continue; 915 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 916 << getOpenMPContextTraitSetName( 917 getOpenMPContextTraitSetForProperty(PropertyForName)) 918 << getOpenMPContextTraitSelectorName( 919 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 920 << ("(" + Name + ")").str(); 921 return; 922 } 923 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 924 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector); 925 } 926 927 static bool checkExtensionProperty(Parser &P, SourceLocation Loc, 928 OMPTraitProperty &TIProperty, 929 OMPTraitSelector &TISelector, 930 llvm::StringMap<SourceLocation> &Seen) { 931 assert(TISelector.Kind == 932 llvm::omp::TraitSelector::implementation_extension && 933 "Only for extension properties, e.g., " 934 "`implementation={extension(PROPERTY)}`"); 935 if (TIProperty.Kind == TraitProperty::invalid) 936 return false; 937 938 if (TIProperty.Kind == 939 TraitProperty::implementation_extension_disable_implicit_base) 940 return true; 941 942 if (TIProperty.Kind == 943 TraitProperty::implementation_extension_allow_templates) 944 return true; 945 946 auto IsMatchExtension = [](OMPTraitProperty &TP) { 947 return (TP.Kind == 948 llvm::omp::TraitProperty::implementation_extension_match_all || 949 TP.Kind == 950 llvm::omp::TraitProperty::implementation_extension_match_any || 951 TP.Kind == 952 llvm::omp::TraitProperty::implementation_extension_match_none); 953 }; 954 955 if (IsMatchExtension(TIProperty)) { 956 for (OMPTraitProperty &SeenProp : TISelector.Properties) 957 if (IsMatchExtension(SeenProp)) { 958 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension); 959 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName( 960 SeenProp.Kind, SeenProp.RawString); 961 SourceLocation SeenLoc = Seen[SeenName]; 962 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here) 963 << CONTEXT_TRAIT_LVL << SeenName; 964 return false; 965 } 966 return true; 967 } 968 969 llvm_unreachable("Unknown extension property!"); 970 } 971 972 void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector, 973 llvm::omp::TraitSet Set, 974 llvm::StringMap<SourceLocation> &Seen) { 975 assert(TISelector.Kind != TraitSelector::user_condition && 976 "User conditions are special properties not handled here!"); 977 978 SourceLocation PropertyLoc = Tok.getLocation(); 979 OMPTraitProperty TIProperty; 980 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen); 981 982 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension) 983 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty, 984 TISelector, Seen)) 985 TIProperty.Kind = TraitProperty::invalid; 986 987 // If we have an invalid property here we already issued a warning. 988 if (TIProperty.Kind == TraitProperty::invalid) { 989 if (PropertyLoc != Tok.getLocation()) 990 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 991 << CONTEXT_TRAIT_LVL; 992 return; 993 } 994 995 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind, 996 TISelector.Kind, Set)) { 997 998 // If we make it here the property, selector, set, score, condition, ... are 999 // all valid (or have been corrected). Thus we can record the property. 1000 TISelector.Properties.push_back(TIProperty); 1001 return; 1002 } 1003 1004 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector) 1005 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 1006 TIProperty.RawString) 1007 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1008 << getOpenMPContextTraitSetName(Set); 1009 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property) 1010 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 1011 TIProperty.RawString) 1012 << getOpenMPContextTraitSelectorName( 1013 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind)) 1014 << getOpenMPContextTraitSetName( 1015 getOpenMPContextTraitSetForProperty(TIProperty.Kind)); 1016 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1017 << CONTEXT_TRAIT_LVL; 1018 } 1019 1020 void Parser::parseOMPTraitSelectorKind( 1021 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1022 llvm::StringMap<SourceLocation> &Seen) { 1023 TISelector.Kind = TraitSelector::invalid; 1024 1025 SourceLocation NameLoc = Tok.getLocation(); 1026 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL 1027 ); 1028 if (Name.empty()) { 1029 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1030 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1031 return; 1032 } 1033 1034 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name); 1035 if (TISelector.Kind != TraitSelector::invalid) { 1036 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL)) 1037 TISelector.Kind = TraitSelector::invalid; 1038 return; 1039 } 1040 1041 // It follows diagnosis and helping notes. 1042 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector) 1043 << Name << getOpenMPContextTraitSetName(Set); 1044 1045 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 1046 if (SetForName != TraitSet::invalid) { 1047 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1048 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL; 1049 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1050 << Name << "<selector-name>" 1051 << "<property-name>"; 1052 return; 1053 } 1054 for (const auto &PotentialSet : 1055 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1056 TraitSet::device}) { 1057 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1058 PotentialSet, TraitSelector::invalid, Name); 1059 if (PropertyForName == TraitProperty::invalid) 1060 continue; 1061 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1062 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL; 1063 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1064 << getOpenMPContextTraitSetName( 1065 getOpenMPContextTraitSetForProperty(PropertyForName)) 1066 << getOpenMPContextTraitSelectorName( 1067 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1068 << ("(" + Name + ")").str(); 1069 return; 1070 } 1071 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1072 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1073 } 1074 1075 /// Parse optional 'score' '(' <expr> ')' ':'. 1076 static ExprResult parseContextScore(Parser &P) { 1077 ExprResult ScoreExpr; 1078 llvm::SmallString<16> Buffer; 1079 StringRef SelectorName = 1080 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 1081 if (!SelectorName.equals("score")) 1082 return ScoreExpr; 1083 (void)P.ConsumeToken(); 1084 SourceLocation RLoc; 1085 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); 1086 // Parse ':' 1087 if (P.getCurToken().is(tok::colon)) 1088 (void)P.ConsumeAnyToken(); 1089 else 1090 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected) 1091 << "':'" 1092 << "score expression"; 1093 return ScoreExpr; 1094 } 1095 1096 /// Parses an OpenMP context selector. 1097 /// 1098 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')'] 1099 void Parser::parseOMPContextSelector( 1100 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1101 llvm::StringMap<SourceLocation> &SeenSelectors) { 1102 unsigned short OuterPC = ParenCount; 1103 1104 // If anything went wrong we issue an error or warning and then skip the rest 1105 // of the selector. However, commas are ambiguous so we look for the nesting 1106 // of parentheses here as well. 1107 auto FinishSelector = [OuterPC, this]() -> void { 1108 bool Done = false; 1109 while (!Done) { 1110 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma, 1111 tok::annot_pragma_openmp_end}, 1112 StopBeforeMatch)) 1113 ; 1114 if (Tok.is(tok::r_paren) && OuterPC > ParenCount) 1115 (void)ConsumeParen(); 1116 if (OuterPC <= ParenCount) { 1117 Done = true; 1118 break; 1119 } 1120 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) { 1121 Done = true; 1122 break; 1123 } 1124 (void)ConsumeAnyToken(); 1125 } 1126 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1127 << CONTEXT_SELECTOR_LVL; 1128 }; 1129 1130 SourceLocation SelectorLoc = Tok.getLocation(); 1131 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors); 1132 if (TISelector.Kind == TraitSelector::invalid) 1133 return FinishSelector(); 1134 1135 bool AllowsTraitScore = false; 1136 bool RequiresProperty = false; 1137 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore, 1138 RequiresProperty)) { 1139 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set) 1140 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1141 << getOpenMPContextTraitSetName(Set); 1142 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector) 1143 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1144 << getOpenMPContextTraitSetName( 1145 getOpenMPContextTraitSetForSelector(TISelector.Kind)) 1146 << RequiresProperty; 1147 return FinishSelector(); 1148 } 1149 1150 if (!RequiresProperty) { 1151 TISelector.Properties.push_back( 1152 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind), 1153 getOpenMPContextTraitSelectorName(TISelector.Kind)}); 1154 return; 1155 } 1156 1157 if (!Tok.is(tok::l_paren)) { 1158 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties) 1159 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1160 << getOpenMPContextTraitSetName(Set); 1161 return FinishSelector(); 1162 } 1163 1164 if (TISelector.Kind == TraitSelector::user_condition) { 1165 SourceLocation RLoc; 1166 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc); 1167 if (!Condition.isUsable()) 1168 return FinishSelector(); 1169 TISelector.ScoreOrCondition = Condition.get(); 1170 TISelector.Properties.push_back( 1171 {TraitProperty::user_condition_unknown, "<condition>"}); 1172 return; 1173 } 1174 1175 BalancedDelimiterTracker BDT(*this, tok::l_paren, 1176 tok::annot_pragma_openmp_end); 1177 // Parse '('. 1178 (void)BDT.consumeOpen(); 1179 1180 SourceLocation ScoreLoc = Tok.getLocation(); 1181 ExprResult Score = parseContextScore(*this); 1182 1183 if (!AllowsTraitScore && !Score.isUnset()) { 1184 if (Score.isUsable()) { 1185 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1186 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1187 << getOpenMPContextTraitSetName(Set) << Score.get(); 1188 } else { 1189 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1190 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1191 << getOpenMPContextTraitSetName(Set) << "<invalid>"; 1192 } 1193 Score = ExprResult(); 1194 } 1195 1196 if (Score.isUsable()) 1197 TISelector.ScoreOrCondition = Score.get(); 1198 1199 llvm::StringMap<SourceLocation> SeenProperties; 1200 do { 1201 parseOMPContextProperty(TISelector, Set, SeenProperties); 1202 } while (TryConsumeToken(tok::comma)); 1203 1204 // Parse ')'. 1205 BDT.consumeClose(); 1206 } 1207 1208 void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet, 1209 llvm::StringMap<SourceLocation> &Seen) { 1210 TISet.Kind = TraitSet::invalid; 1211 1212 SourceLocation NameLoc = Tok.getLocation(); 1213 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL 1214 ); 1215 if (Name.empty()) { 1216 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1217 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1218 return; 1219 } 1220 1221 TISet.Kind = getOpenMPContextTraitSetKind(Name); 1222 if (TISet.Kind != TraitSet::invalid) { 1223 if (checkForDuplicates(*this, Name, NameLoc, Seen, 1224 CONTEXT_SELECTOR_SET_LVL)) 1225 TISet.Kind = TraitSet::invalid; 1226 return; 1227 } 1228 1229 // It follows diagnosis and helping notes. 1230 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name; 1231 1232 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 1233 if (SelectorForName != TraitSelector::invalid) { 1234 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1235 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL; 1236 bool AllowsTraitScore = false; 1237 bool RequiresProperty = false; 1238 isValidTraitSelectorForTraitSet( 1239 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 1240 AllowsTraitScore, RequiresProperty); 1241 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1242 << getOpenMPContextTraitSetName( 1243 getOpenMPContextTraitSetForSelector(SelectorForName)) 1244 << Name << (RequiresProperty ? "(<property-name>)" : ""); 1245 return; 1246 } 1247 for (const auto &PotentialSet : 1248 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1249 TraitSet::device}) { 1250 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1251 PotentialSet, TraitSelector::invalid, Name); 1252 if (PropertyForName == TraitProperty::invalid) 1253 continue; 1254 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1255 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL; 1256 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1257 << getOpenMPContextTraitSetName( 1258 getOpenMPContextTraitSetForProperty(PropertyForName)) 1259 << getOpenMPContextTraitSelectorName( 1260 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1261 << ("(" + Name + ")").str(); 1262 return; 1263 } 1264 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1265 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1266 } 1267 1268 /// Parses an OpenMP context selector set. 1269 /// 1270 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}' 1271 void Parser::parseOMPContextSelectorSet( 1272 OMPTraitSet &TISet, 1273 llvm::StringMap<SourceLocation> &SeenSets) { 1274 auto OuterBC = BraceCount; 1275 1276 // If anything went wrong we issue an error or warning and then skip the rest 1277 // of the set. However, commas are ambiguous so we look for the nesting 1278 // of braces here as well. 1279 auto FinishSelectorSet = [this, OuterBC]() -> void { 1280 bool Done = false; 1281 while (!Done) { 1282 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren, 1283 tok::annot_pragma_openmp_end}, 1284 StopBeforeMatch)) 1285 ; 1286 if (Tok.is(tok::r_brace) && OuterBC > BraceCount) 1287 (void)ConsumeBrace(); 1288 if (OuterBC <= BraceCount) { 1289 Done = true; 1290 break; 1291 } 1292 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) { 1293 Done = true; 1294 break; 1295 } 1296 (void)ConsumeAnyToken(); 1297 } 1298 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1299 << CONTEXT_SELECTOR_SET_LVL; 1300 }; 1301 1302 parseOMPTraitSetKind(TISet, SeenSets); 1303 if (TISet.Kind == TraitSet::invalid) 1304 return FinishSelectorSet(); 1305 1306 // Parse '='. 1307 if (!TryConsumeToken(tok::equal)) 1308 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1309 << "=" 1310 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) + 1311 "\"") 1312 .str(); 1313 1314 // Parse '{'. 1315 if (Tok.is(tok::l_brace)) { 1316 (void)ConsumeBrace(); 1317 } else { 1318 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1319 << "{" 1320 << ("'=' that follows the context set name \"" + 1321 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1322 .str(); 1323 } 1324 1325 llvm::StringMap<SourceLocation> SeenSelectors; 1326 do { 1327 OMPTraitSelector TISelector; 1328 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors); 1329 if (TISelector.Kind != TraitSelector::invalid && 1330 !TISelector.Properties.empty()) 1331 TISet.Selectors.push_back(TISelector); 1332 } while (TryConsumeToken(tok::comma)); 1333 1334 // Parse '}'. 1335 if (Tok.is(tok::r_brace)) { 1336 (void)ConsumeBrace(); 1337 } else { 1338 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1339 << "}" 1340 << ("context selectors for the context set \"" + 1341 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1342 .str(); 1343 } 1344 } 1345 1346 /// Parse OpenMP context selectors: 1347 /// 1348 /// <trait-set-selector> [, <trait-set-selector>]* 1349 bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo& TI) { 1350 llvm::StringMap<SourceLocation> SeenSets; 1351 do { 1352 OMPTraitSet TISet; 1353 parseOMPContextSelectorSet(TISet, SeenSets); 1354 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty()) 1355 TI.Sets.push_back(TISet); 1356 } while (TryConsumeToken(tok::comma)); 1357 1358 return false; 1359 } 1360 1361 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. 1362 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, 1363 CachedTokens &Toks, 1364 SourceLocation Loc) { 1365 PP.EnterToken(Tok, /*IsReinject*/ true); 1366 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1367 /*IsReinject*/ true); 1368 // Consume the previously pushed token. 1369 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1370 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1371 1372 FNContextRAII FnContext(*this, Ptr); 1373 // Parse function declaration id. 1374 SourceLocation RLoc; 1375 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs 1376 // instead of MemberExprs. 1377 ExprResult AssociatedFunction; 1378 { 1379 // Do not mark function as is used to prevent its emission if this is the 1380 // only place where it is used. 1381 EnterExpressionEvaluationContext Unevaluated( 1382 Actions, Sema::ExpressionEvaluationContext::Unevaluated); 1383 AssociatedFunction = ParseOpenMPParensExpr( 1384 getOpenMPDirectiveName(OMPD_declare_variant), RLoc, 1385 /*IsAddressOfOperand=*/true); 1386 } 1387 if (!AssociatedFunction.isUsable()) { 1388 if (!Tok.is(tok::annot_pragma_openmp_end)) 1389 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1390 ; 1391 // Skip the last annot_pragma_openmp_end. 1392 (void)ConsumeAnnotationToken(); 1393 return; 1394 } 1395 1396 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope(); 1397 ASTContext &ASTCtx = Actions.getASTContext(); 1398 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); 1399 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) 1400 return; 1401 1402 Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = 1403 Actions.checkOpenMPDeclareVariantFunction( 1404 Ptr, AssociatedFunction.get(), TI, 1405 SourceRange(Loc, Tok.getLocation())); 1406 1407 // Skip last tokens. 1408 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1409 ConsumeAnyToken(); 1410 if (DeclVarData && !TI.Sets.empty()) 1411 Actions.ActOnOpenMPDeclareVariantDirective( 1412 DeclVarData->first, DeclVarData->second, TI, 1413 SourceRange(Loc, Tok.getLocation())); 1414 1415 // Skip the last annot_pragma_openmp_end. 1416 (void)ConsumeAnnotationToken(); 1417 } 1418 1419 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, 1420 OMPTraitInfo &TI, 1421 OMPTraitInfo *ParentTI) { 1422 // Parse 'match'. 1423 OpenMPClauseKind CKind = Tok.isAnnotation() 1424 ? OMPC_unknown 1425 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1426 if (CKind != OMPC_match) { 1427 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1428 << getOpenMPClauseName(OMPC_match); 1429 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 1430 ; 1431 // Skip the last annot_pragma_openmp_end. 1432 (void)ConsumeAnnotationToken(); 1433 return true; 1434 } 1435 (void)ConsumeToken(); 1436 // Parse '('. 1437 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1438 if (T.expectAndConsume(diag::err_expected_lparen_after, 1439 getOpenMPClauseName(OMPC_match).data())) { 1440 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1441 ; 1442 // Skip the last annot_pragma_openmp_end. 1443 (void)ConsumeAnnotationToken(); 1444 return true; 1445 } 1446 1447 // Parse inner context selectors. 1448 parseOMPContextSelectors(Loc, TI); 1449 1450 // Parse ')' 1451 (void)T.consumeClose(); 1452 1453 if (!ParentTI) 1454 return false; 1455 1456 // Merge the parent/outer trait info into the one we just parsed and diagnose 1457 // problems. 1458 // TODO: Keep some source location in the TI to provide better diagnostics. 1459 // TODO: Perform some kind of equivalence check on the condition and score 1460 // expressions. 1461 for (const OMPTraitSet &ParentSet : ParentTI->Sets) { 1462 bool MergedSet = false; 1463 for (OMPTraitSet &Set : TI.Sets) { 1464 if (Set.Kind != ParentSet.Kind) 1465 continue; 1466 MergedSet = true; 1467 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) { 1468 bool MergedSelector = false; 1469 for (OMPTraitSelector &Selector : Set.Selectors) { 1470 if (Selector.Kind != ParentSelector.Kind) 1471 continue; 1472 MergedSelector = true; 1473 for (const OMPTraitProperty &ParentProperty : 1474 ParentSelector.Properties) { 1475 bool MergedProperty = false; 1476 for (OMPTraitProperty &Property : Selector.Properties) { 1477 // Ignore "equivalent" properties. 1478 if (Property.Kind != ParentProperty.Kind) 1479 continue; 1480 1481 // If the kind is the same but the raw string not, we don't want 1482 // to skip out on the property. 1483 MergedProperty |= Property.RawString == ParentProperty.RawString; 1484 1485 if (Property.RawString == ParentProperty.RawString && 1486 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition) 1487 continue; 1488 1489 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) { 1490 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition); 1491 } else if (Selector.ScoreOrCondition != 1492 ParentSelector.ScoreOrCondition) { 1493 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait) 1494 << getOpenMPContextTraitPropertyName( 1495 ParentProperty.Kind, ParentProperty.RawString) 1496 << getOpenMPContextTraitSelectorName(ParentSelector.Kind) 1497 << getOpenMPContextTraitSetName(ParentSet.Kind); 1498 } 1499 } 1500 if (!MergedProperty) 1501 Selector.Properties.push_back(ParentProperty); 1502 } 1503 } 1504 if (!MergedSelector) 1505 Set.Selectors.push_back(ParentSelector); 1506 } 1507 } 1508 if (!MergedSet) 1509 TI.Sets.push_back(ParentSet); 1510 } 1511 1512 return false; 1513 } 1514 1515 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1516 /// 1517 /// default-clause: 1518 /// 'default' '(' 'none' | 'shared' | 'firstprivate' ') 1519 /// 1520 /// proc_bind-clause: 1521 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1522 /// 1523 /// device_type-clause: 1524 /// 'device_type' '(' 'host' | 'nohost' | 'any' )' 1525 namespace { 1526 struct SimpleClauseData { 1527 unsigned Type; 1528 SourceLocation Loc; 1529 SourceLocation LOpen; 1530 SourceLocation TypeLoc; 1531 SourceLocation RLoc; 1532 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, 1533 SourceLocation TypeLoc, SourceLocation RLoc) 1534 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} 1535 }; 1536 } // anonymous namespace 1537 1538 static Optional<SimpleClauseData> 1539 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { 1540 const Token &Tok = P.getCurToken(); 1541 SourceLocation Loc = Tok.getLocation(); 1542 SourceLocation LOpen = P.ConsumeToken(); 1543 // Parse '('. 1544 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 1545 if (T.expectAndConsume(diag::err_expected_lparen_after, 1546 getOpenMPClauseName(Kind).data())) 1547 return llvm::None; 1548 1549 unsigned Type = getOpenMPSimpleClauseType( 1550 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok), 1551 P.getLangOpts().OpenMP); 1552 SourceLocation TypeLoc = Tok.getLocation(); 1553 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1554 Tok.isNot(tok::annot_pragma_openmp_end)) 1555 P.ConsumeAnyToken(); 1556 1557 // Parse ')'. 1558 SourceLocation RLoc = Tok.getLocation(); 1559 if (!T.consumeClose()) 1560 RLoc = T.getCloseLocation(); 1561 1562 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); 1563 } 1564 1565 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { 1566 // OpenMP 4.5 syntax with list of entities. 1567 Sema::NamedDeclSetType SameDirectiveDecls; 1568 SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation, 1569 NamedDecl *>, 1570 4> 1571 DeclareTargetDecls; 1572 OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; 1573 SourceLocation DeviceTypeLoc; 1574 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1575 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 1576 if (Tok.is(tok::identifier)) { 1577 IdentifierInfo *II = Tok.getIdentifierInfo(); 1578 StringRef ClauseName = II->getName(); 1579 bool IsDeviceTypeClause = 1580 getLangOpts().OpenMP >= 50 && 1581 getOpenMPClauseKind(ClauseName) == OMPC_device_type; 1582 // Parse 'to|link|device_type' clauses. 1583 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) && 1584 !IsDeviceTypeClause) { 1585 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1586 << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0); 1587 break; 1588 } 1589 // Parse 'device_type' clause and go to next clause if any. 1590 if (IsDeviceTypeClause) { 1591 Optional<SimpleClauseData> DevTypeData = 1592 parseOpenMPSimpleClause(*this, OMPC_device_type); 1593 if (DevTypeData.hasValue()) { 1594 if (DeviceTypeLoc.isValid()) { 1595 // We already saw another device_type clause, diagnose it. 1596 Diag(DevTypeData.getValue().Loc, 1597 diag::warn_omp_more_one_device_type_clause); 1598 } 1599 switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { 1600 case OMPC_DEVICE_TYPE_any: 1601 DT = OMPDeclareTargetDeclAttr::DT_Any; 1602 break; 1603 case OMPC_DEVICE_TYPE_host: 1604 DT = OMPDeclareTargetDeclAttr::DT_Host; 1605 break; 1606 case OMPC_DEVICE_TYPE_nohost: 1607 DT = OMPDeclareTargetDeclAttr::DT_NoHost; 1608 break; 1609 case OMPC_DEVICE_TYPE_unknown: 1610 llvm_unreachable("Unexpected device_type"); 1611 } 1612 DeviceTypeLoc = DevTypeData.getValue().Loc; 1613 } 1614 continue; 1615 } 1616 ConsumeToken(); 1617 } 1618 auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls]( 1619 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 1620 NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName( 1621 getCurScope(), SS, NameInfo, SameDirectiveDecls); 1622 if (ND) 1623 DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND); 1624 }; 1625 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 1626 /*AllowScopeSpecifier=*/true)) 1627 break; 1628 1629 // Consume optional ','. 1630 if (Tok.is(tok::comma)) 1631 ConsumeToken(); 1632 } 1633 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1634 ConsumeAnyToken(); 1635 for (auto &MTLocDecl : DeclareTargetDecls) { 1636 OMPDeclareTargetDeclAttr::MapTypeTy MT; 1637 SourceLocation Loc; 1638 NamedDecl *ND; 1639 std::tie(MT, Loc, ND) = MTLocDecl; 1640 // device_type clause is applied only to functions. 1641 Actions.ActOnOpenMPDeclareTargetName( 1642 ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT); 1643 } 1644 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), 1645 SameDirectiveDecls.end()); 1646 if (Decls.empty()) 1647 return DeclGroupPtrTy(); 1648 return Actions.BuildDeclaratorGroup(Decls); 1649 } 1650 1651 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) { 1652 // The last seen token is annot_pragma_openmp_end - need to check for 1653 // extra tokens. 1654 if (Tok.is(tok::annot_pragma_openmp_end)) 1655 return; 1656 1657 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1658 << getOpenMPDirectiveName(DKind); 1659 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1660 ConsumeAnyToken(); 1661 } 1662 1663 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind, 1664 OpenMPDirectiveKind ExpectedKind, 1665 OpenMPDirectiveKind FoundKind, 1666 SourceLocation BeginLoc, 1667 SourceLocation FoundLoc, 1668 bool SkipUntilOpenMPEnd) { 1669 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1; 1670 1671 if (FoundKind == ExpectedKind) { 1672 ConsumeAnyToken(); 1673 skipUntilPragmaOpenMPEnd(ExpectedKind); 1674 return; 1675 } 1676 1677 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant) 1678 << DiagSelection; 1679 Diag(BeginLoc, diag::note_matching) 1680 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str(); 1681 if (SkipUntilOpenMPEnd) 1682 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1683 } 1684 1685 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, 1686 SourceLocation DKLoc) { 1687 parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind, 1688 DKLoc, Tok.getLocation(), 1689 /* SkipUntilOpenMPEnd */ false); 1690 // Skip the last annot_pragma_openmp_end. 1691 if (Tok.is(tok::annot_pragma_openmp_end)) 1692 ConsumeAnnotationToken(); 1693 } 1694 1695 /// Parsing of declarative OpenMP directives. 1696 /// 1697 /// threadprivate-directive: 1698 /// annot_pragma_openmp 'threadprivate' simple-variable-list 1699 /// annot_pragma_openmp_end 1700 /// 1701 /// allocate-directive: 1702 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 1703 /// annot_pragma_openmp_end 1704 /// 1705 /// declare-reduction-directive: 1706 /// annot_pragma_openmp 'declare' 'reduction' [...] 1707 /// annot_pragma_openmp_end 1708 /// 1709 /// declare-mapper-directive: 1710 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 1711 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 1712 /// annot_pragma_openmp_end 1713 /// 1714 /// declare-simd-directive: 1715 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 1716 /// annot_pragma_openmp_end 1717 /// <function declaration/definition> 1718 /// 1719 /// requires directive: 1720 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 1721 /// annot_pragma_openmp_end 1722 /// 1723 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 1724 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, 1725 DeclSpec::TST TagType, Decl *Tag) { 1726 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 1727 ParsingOpenMPDirectiveRAII DirScope(*this); 1728 ParenBraceBracketBalancer BalancerRAIIObj(*this); 1729 1730 SourceLocation Loc; 1731 OpenMPDirectiveKind DKind; 1732 if (Delayed) { 1733 TentativeParsingAction TPA(*this); 1734 Loc = ConsumeAnnotationToken(); 1735 DKind = parseOpenMPDirectiveKind(*this); 1736 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { 1737 // Need to delay parsing until completion of the parent class. 1738 TPA.Revert(); 1739 CachedTokens Toks; 1740 unsigned Cnt = 1; 1741 Toks.push_back(Tok); 1742 while (Cnt && Tok.isNot(tok::eof)) { 1743 (void)ConsumeAnyToken(); 1744 if (Tok.is(tok::annot_pragma_openmp)) 1745 ++Cnt; 1746 else if (Tok.is(tok::annot_pragma_openmp_end)) 1747 --Cnt; 1748 Toks.push_back(Tok); 1749 } 1750 // Skip last annot_pragma_openmp_end. 1751 if (Cnt == 0) 1752 (void)ConsumeAnyToken(); 1753 auto *LP = new LateParsedPragma(this, AS); 1754 LP->takeToks(Toks); 1755 getCurrentClass().LateParsedDeclarations.push_back(LP); 1756 return nullptr; 1757 } 1758 TPA.Commit(); 1759 } else { 1760 Loc = ConsumeAnnotationToken(); 1761 DKind = parseOpenMPDirectiveKind(*this); 1762 } 1763 1764 switch (DKind) { 1765 case OMPD_threadprivate: { 1766 ConsumeToken(); 1767 DeclDirectiveListParserHelper Helper(this, DKind); 1768 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1769 /*AllowScopeSpecifier=*/true)) { 1770 skipUntilPragmaOpenMPEnd(DKind); 1771 // Skip the last annot_pragma_openmp_end. 1772 ConsumeAnnotationToken(); 1773 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 1774 Helper.getIdentifiers()); 1775 } 1776 break; 1777 } 1778 case OMPD_allocate: { 1779 ConsumeToken(); 1780 DeclDirectiveListParserHelper Helper(this, DKind); 1781 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1782 /*AllowScopeSpecifier=*/true)) { 1783 SmallVector<OMPClause *, 1> Clauses; 1784 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1785 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1786 llvm::omp::Clause_enumSize + 1> 1787 FirstClauses(llvm::omp::Clause_enumSize + 1); 1788 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1789 OpenMPClauseKind CKind = 1790 Tok.isAnnotation() ? OMPC_unknown 1791 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1792 Actions.StartOpenMPClause(CKind); 1793 OMPClause *Clause = ParseOpenMPClause( 1794 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 1795 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1796 StopBeforeMatch); 1797 FirstClauses[unsigned(CKind)].setInt(true); 1798 if (Clause != nullptr) 1799 Clauses.push_back(Clause); 1800 if (Tok.is(tok::annot_pragma_openmp_end)) { 1801 Actions.EndOpenMPClause(); 1802 break; 1803 } 1804 // Skip ',' if any. 1805 if (Tok.is(tok::comma)) 1806 ConsumeToken(); 1807 Actions.EndOpenMPClause(); 1808 } 1809 skipUntilPragmaOpenMPEnd(DKind); 1810 } 1811 // Skip the last annot_pragma_openmp_end. 1812 ConsumeAnnotationToken(); 1813 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 1814 Clauses); 1815 } 1816 break; 1817 } 1818 case OMPD_requires: { 1819 SourceLocation StartLoc = ConsumeToken(); 1820 SmallVector<OMPClause *, 5> Clauses; 1821 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1822 llvm::omp::Clause_enumSize + 1> 1823 FirstClauses(llvm::omp::Clause_enumSize + 1); 1824 if (Tok.is(tok::annot_pragma_openmp_end)) { 1825 Diag(Tok, diag::err_omp_expected_clause) 1826 << getOpenMPDirectiveName(OMPD_requires); 1827 break; 1828 } 1829 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1830 OpenMPClauseKind CKind = Tok.isAnnotation() 1831 ? OMPC_unknown 1832 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1833 Actions.StartOpenMPClause(CKind); 1834 OMPClause *Clause = ParseOpenMPClause( 1835 OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt()); 1836 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1837 StopBeforeMatch); 1838 FirstClauses[unsigned(CKind)].setInt(true); 1839 if (Clause != nullptr) 1840 Clauses.push_back(Clause); 1841 if (Tok.is(tok::annot_pragma_openmp_end)) { 1842 Actions.EndOpenMPClause(); 1843 break; 1844 } 1845 // Skip ',' if any. 1846 if (Tok.is(tok::comma)) 1847 ConsumeToken(); 1848 Actions.EndOpenMPClause(); 1849 } 1850 // Consume final annot_pragma_openmp_end 1851 if (Clauses.empty()) { 1852 Diag(Tok, diag::err_omp_expected_clause) 1853 << getOpenMPDirectiveName(OMPD_requires); 1854 ConsumeAnnotationToken(); 1855 return nullptr; 1856 } 1857 ConsumeAnnotationToken(); 1858 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 1859 } 1860 case OMPD_declare_reduction: 1861 ConsumeToken(); 1862 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 1863 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 1864 // Skip the last annot_pragma_openmp_end. 1865 ConsumeAnnotationToken(); 1866 return Res; 1867 } 1868 break; 1869 case OMPD_declare_mapper: { 1870 ConsumeToken(); 1871 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 1872 // Skip the last annot_pragma_openmp_end. 1873 ConsumeAnnotationToken(); 1874 return Res; 1875 } 1876 break; 1877 } 1878 case OMPD_begin_declare_variant: { 1879 // The syntax is: 1880 // { #pragma omp begin declare variant clause } 1881 // <function-declaration-or-definition-sequence> 1882 // { #pragma omp end declare variant } 1883 // 1884 ConsumeToken(); 1885 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope(); 1886 ASTContext &ASTCtx = Actions.getASTContext(); 1887 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); 1888 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) 1889 break; 1890 1891 // Skip last tokens. 1892 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant); 1893 1894 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 1895 1896 VariantMatchInfo VMI; 1897 TI.getAsVariantMatchInfo(ASTCtx, VMI); 1898 1899 std::function<void(StringRef)> DiagUnknownTrait = [this, Loc]( 1900 StringRef ISATrait) { 1901 // TODO Track the selector locations in a way that is accessible here to 1902 // improve the diagnostic location. 1903 Diag(Loc, diag::warn_unknown_begin_declare_variant_isa_trait) << ISATrait; 1904 }; 1905 TargetOMPContext OMPCtx(ASTCtx, std::move(DiagUnknownTrait), 1906 /* CurrentFunctionDecl */ nullptr); 1907 1908 if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) { 1909 Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI); 1910 break; 1911 } 1912 1913 // Elide all the code till the matching end declare variant was found. 1914 unsigned Nesting = 1; 1915 SourceLocation DKLoc; 1916 OpenMPDirectiveKind DK = OMPD_unknown; 1917 do { 1918 DKLoc = Tok.getLocation(); 1919 DK = parseOpenMPDirectiveKind(*this); 1920 if (DK == OMPD_end_declare_variant) 1921 --Nesting; 1922 else if (DK == OMPD_begin_declare_variant) 1923 ++Nesting; 1924 if (!Nesting || isEofOrEom()) 1925 break; 1926 ConsumeAnyToken(); 1927 } while (true); 1928 1929 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, 1930 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true); 1931 if (isEofOrEom()) 1932 return nullptr; 1933 break; 1934 } 1935 case OMPD_end_declare_variant: { 1936 if (Actions.isInOpenMPDeclareVariantScope()) 1937 Actions.ActOnOpenMPEndDeclareVariant(); 1938 else 1939 Diag(Loc, diag::err_expected_begin_declare_variant); 1940 ConsumeToken(); 1941 break; 1942 } 1943 case OMPD_declare_variant: 1944 case OMPD_declare_simd: { 1945 // The syntax is: 1946 // { #pragma omp declare {simd|variant} } 1947 // <function-declaration-or-definition> 1948 // 1949 CachedTokens Toks; 1950 Toks.push_back(Tok); 1951 ConsumeToken(); 1952 while(Tok.isNot(tok::annot_pragma_openmp_end)) { 1953 Toks.push_back(Tok); 1954 ConsumeAnyToken(); 1955 } 1956 Toks.push_back(Tok); 1957 ConsumeAnyToken(); 1958 1959 DeclGroupPtrTy Ptr; 1960 if (Tok.is(tok::annot_pragma_openmp)) { 1961 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, 1962 TagType, Tag); 1963 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 1964 // Here we expect to see some function declaration. 1965 if (AS == AS_none) { 1966 assert(TagType == DeclSpec::TST_unspecified); 1967 MaybeParseCXX11Attributes(Attrs); 1968 ParsingDeclSpec PDS(*this); 1969 Ptr = ParseExternalDeclaration(Attrs, &PDS); 1970 } else { 1971 Ptr = 1972 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1973 } 1974 } 1975 if (!Ptr) { 1976 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) 1977 << (DKind == OMPD_declare_simd ? 0 : 1); 1978 return DeclGroupPtrTy(); 1979 } 1980 if (DKind == OMPD_declare_simd) 1981 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 1982 assert(DKind == OMPD_declare_variant && 1983 "Expected declare variant directive only"); 1984 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); 1985 return Ptr; 1986 } 1987 case OMPD_declare_target: { 1988 SourceLocation DTLoc = ConsumeAnyToken(); 1989 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1990 return ParseOMPDeclareTargetClauses(); 1991 } 1992 1993 // Skip the last annot_pragma_openmp_end. 1994 ConsumeAnyToken(); 1995 1996 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 1997 return DeclGroupPtrTy(); 1998 1999 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2000 llvm::SmallVector<Decl *, 4> Decls; 2001 DKind = parseOpenMPDirectiveKind(*this); 2002 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && 2003 Tok.isNot(tok::r_brace)) { 2004 DeclGroupPtrTy Ptr; 2005 // Here we expect to see some function declaration. 2006 if (AS == AS_none) { 2007 assert(TagType == DeclSpec::TST_unspecified); 2008 MaybeParseCXX11Attributes(Attrs); 2009 ParsingDeclSpec PDS(*this); 2010 Ptr = ParseExternalDeclaration(Attrs, &PDS); 2011 } else { 2012 Ptr = 2013 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 2014 } 2015 if (Ptr) { 2016 DeclGroupRef Ref = Ptr.get(); 2017 Decls.append(Ref.begin(), Ref.end()); 2018 } 2019 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 2020 TentativeParsingAction TPA(*this); 2021 ConsumeAnnotationToken(); 2022 DKind = parseOpenMPDirectiveKind(*this); 2023 if (DKind != OMPD_end_declare_target) 2024 TPA.Revert(); 2025 else 2026 TPA.Commit(); 2027 } 2028 } 2029 2030 ParseOMPEndDeclareTargetDirective(DKind, DTLoc); 2031 Actions.ActOnFinishOpenMPDeclareTargetDirective(); 2032 return Actions.BuildDeclaratorGroup(Decls); 2033 } 2034 case OMPD_unknown: 2035 Diag(Tok, diag::err_omp_unknown_directive); 2036 break; 2037 case OMPD_parallel: 2038 case OMPD_simd: 2039 case OMPD_task: 2040 case OMPD_taskyield: 2041 case OMPD_barrier: 2042 case OMPD_taskwait: 2043 case OMPD_taskgroup: 2044 case OMPD_flush: 2045 case OMPD_depobj: 2046 case OMPD_scan: 2047 case OMPD_for: 2048 case OMPD_for_simd: 2049 case OMPD_sections: 2050 case OMPD_section: 2051 case OMPD_single: 2052 case OMPD_master: 2053 case OMPD_ordered: 2054 case OMPD_critical: 2055 case OMPD_parallel_for: 2056 case OMPD_parallel_for_simd: 2057 case OMPD_parallel_sections: 2058 case OMPD_parallel_master: 2059 case OMPD_atomic: 2060 case OMPD_target: 2061 case OMPD_teams: 2062 case OMPD_cancellation_point: 2063 case OMPD_cancel: 2064 case OMPD_target_data: 2065 case OMPD_target_enter_data: 2066 case OMPD_target_exit_data: 2067 case OMPD_target_parallel: 2068 case OMPD_target_parallel_for: 2069 case OMPD_taskloop: 2070 case OMPD_taskloop_simd: 2071 case OMPD_master_taskloop: 2072 case OMPD_master_taskloop_simd: 2073 case OMPD_parallel_master_taskloop: 2074 case OMPD_parallel_master_taskloop_simd: 2075 case OMPD_distribute: 2076 case OMPD_end_declare_target: 2077 case OMPD_target_update: 2078 case OMPD_distribute_parallel_for: 2079 case OMPD_distribute_parallel_for_simd: 2080 case OMPD_distribute_simd: 2081 case OMPD_target_parallel_for_simd: 2082 case OMPD_target_simd: 2083 case OMPD_teams_distribute: 2084 case OMPD_teams_distribute_simd: 2085 case OMPD_teams_distribute_parallel_for_simd: 2086 case OMPD_teams_distribute_parallel_for: 2087 case OMPD_target_teams: 2088 case OMPD_target_teams_distribute: 2089 case OMPD_target_teams_distribute_parallel_for: 2090 case OMPD_target_teams_distribute_parallel_for_simd: 2091 case OMPD_target_teams_distribute_simd: 2092 Diag(Tok, diag::err_omp_unexpected_directive) 2093 << 1 << getOpenMPDirectiveName(DKind); 2094 break; 2095 default: 2096 break; 2097 } 2098 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2099 ConsumeAnyToken(); 2100 ConsumeAnyToken(); 2101 return nullptr; 2102 } 2103 2104 /// Parsing of declarative or executable OpenMP directives. 2105 /// 2106 /// threadprivate-directive: 2107 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2108 /// annot_pragma_openmp_end 2109 /// 2110 /// allocate-directive: 2111 /// annot_pragma_openmp 'allocate' simple-variable-list 2112 /// annot_pragma_openmp_end 2113 /// 2114 /// declare-reduction-directive: 2115 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 2116 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 2117 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 2118 /// annot_pragma_openmp_end 2119 /// 2120 /// declare-mapper-directive: 2121 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2122 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2123 /// annot_pragma_openmp_end 2124 /// 2125 /// executable-directive: 2126 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 2127 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 2128 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | 2129 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 2130 /// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target 2131 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 2132 /// 'master taskloop' | 'master taskloop simd' | 'parallel master 2133 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target 2134 /// enter data' | 'target exit data' | 'target parallel' | 'target 2135 /// parallel for' | 'target update' | 'distribute parallel for' | 2136 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel 2137 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute 2138 /// simd' | 'teams distribute parallel for simd' | 'teams distribute 2139 /// parallel for' | 'target teams' | 'target teams distribute' | 'target 2140 /// teams distribute parallel for' | 'target teams distribute parallel 2141 /// for simd' | 'target teams distribute simd' {clause} 2142 /// annot_pragma_openmp_end 2143 /// 2144 StmtResult 2145 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 2146 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 2147 ParsingOpenMPDirectiveRAII DirScope(*this); 2148 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2149 SmallVector<OMPClause *, 5> Clauses; 2150 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2151 llvm::omp::Clause_enumSize + 1> 2152 FirstClauses(llvm::omp::Clause_enumSize + 1); 2153 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 2154 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 2155 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; 2156 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 2157 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 2158 // Name of critical directive. 2159 DeclarationNameInfo DirName; 2160 StmtResult Directive = StmtError(); 2161 bool HasAssociatedStatement = true; 2162 2163 switch (DKind) { 2164 case OMPD_threadprivate: { 2165 // FIXME: Should this be permitted in C++? 2166 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2167 ParsedStmtContext()) { 2168 Diag(Tok, diag::err_omp_immediate_directive) 2169 << getOpenMPDirectiveName(DKind) << 0; 2170 } 2171 ConsumeToken(); 2172 DeclDirectiveListParserHelper Helper(this, DKind); 2173 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2174 /*AllowScopeSpecifier=*/false)) { 2175 skipUntilPragmaOpenMPEnd(DKind); 2176 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 2177 Loc, Helper.getIdentifiers()); 2178 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2179 } 2180 SkipUntil(tok::annot_pragma_openmp_end); 2181 break; 2182 } 2183 case OMPD_allocate: { 2184 // FIXME: Should this be permitted in C++? 2185 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2186 ParsedStmtContext()) { 2187 Diag(Tok, diag::err_omp_immediate_directive) 2188 << getOpenMPDirectiveName(DKind) << 0; 2189 } 2190 ConsumeToken(); 2191 DeclDirectiveListParserHelper Helper(this, DKind); 2192 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2193 /*AllowScopeSpecifier=*/false)) { 2194 SmallVector<OMPClause *, 1> Clauses; 2195 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2196 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2197 llvm::omp::Clause_enumSize + 1> 2198 FirstClauses(llvm::omp::Clause_enumSize + 1); 2199 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2200 OpenMPClauseKind CKind = 2201 Tok.isAnnotation() ? OMPC_unknown 2202 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2203 Actions.StartOpenMPClause(CKind); 2204 OMPClause *Clause = ParseOpenMPClause( 2205 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2206 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2207 StopBeforeMatch); 2208 FirstClauses[unsigned(CKind)].setInt(true); 2209 if (Clause != nullptr) 2210 Clauses.push_back(Clause); 2211 if (Tok.is(tok::annot_pragma_openmp_end)) { 2212 Actions.EndOpenMPClause(); 2213 break; 2214 } 2215 // Skip ',' if any. 2216 if (Tok.is(tok::comma)) 2217 ConsumeToken(); 2218 Actions.EndOpenMPClause(); 2219 } 2220 skipUntilPragmaOpenMPEnd(DKind); 2221 } 2222 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 2223 Loc, Helper.getIdentifiers(), Clauses); 2224 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2225 } 2226 SkipUntil(tok::annot_pragma_openmp_end); 2227 break; 2228 } 2229 case OMPD_declare_reduction: 2230 ConsumeToken(); 2231 if (DeclGroupPtrTy Res = 2232 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 2233 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2234 ConsumeAnyToken(); 2235 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2236 } else { 2237 SkipUntil(tok::annot_pragma_openmp_end); 2238 } 2239 break; 2240 case OMPD_declare_mapper: { 2241 ConsumeToken(); 2242 if (DeclGroupPtrTy Res = 2243 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 2244 // Skip the last annot_pragma_openmp_end. 2245 ConsumeAnnotationToken(); 2246 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2247 } else { 2248 SkipUntil(tok::annot_pragma_openmp_end); 2249 } 2250 break; 2251 } 2252 case OMPD_flush: 2253 case OMPD_depobj: 2254 case OMPD_scan: 2255 case OMPD_taskyield: 2256 case OMPD_barrier: 2257 case OMPD_taskwait: 2258 case OMPD_cancellation_point: 2259 case OMPD_cancel: 2260 case OMPD_target_enter_data: 2261 case OMPD_target_exit_data: 2262 case OMPD_target_update: 2263 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2264 ParsedStmtContext()) { 2265 Diag(Tok, diag::err_omp_immediate_directive) 2266 << getOpenMPDirectiveName(DKind) << 0; 2267 } 2268 HasAssociatedStatement = false; 2269 // Fall through for further analysis. 2270 LLVM_FALLTHROUGH; 2271 case OMPD_parallel: 2272 case OMPD_simd: 2273 case OMPD_for: 2274 case OMPD_for_simd: 2275 case OMPD_sections: 2276 case OMPD_single: 2277 case OMPD_section: 2278 case OMPD_master: 2279 case OMPD_critical: 2280 case OMPD_parallel_for: 2281 case OMPD_parallel_for_simd: 2282 case OMPD_parallel_sections: 2283 case OMPD_parallel_master: 2284 case OMPD_task: 2285 case OMPD_ordered: 2286 case OMPD_atomic: 2287 case OMPD_target: 2288 case OMPD_teams: 2289 case OMPD_taskgroup: 2290 case OMPD_target_data: 2291 case OMPD_target_parallel: 2292 case OMPD_target_parallel_for: 2293 case OMPD_taskloop: 2294 case OMPD_taskloop_simd: 2295 case OMPD_master_taskloop: 2296 case OMPD_master_taskloop_simd: 2297 case OMPD_parallel_master_taskloop: 2298 case OMPD_parallel_master_taskloop_simd: 2299 case OMPD_distribute: 2300 case OMPD_distribute_parallel_for: 2301 case OMPD_distribute_parallel_for_simd: 2302 case OMPD_distribute_simd: 2303 case OMPD_target_parallel_for_simd: 2304 case OMPD_target_simd: 2305 case OMPD_teams_distribute: 2306 case OMPD_teams_distribute_simd: 2307 case OMPD_teams_distribute_parallel_for_simd: 2308 case OMPD_teams_distribute_parallel_for: 2309 case OMPD_target_teams: 2310 case OMPD_target_teams_distribute: 2311 case OMPD_target_teams_distribute_parallel_for: 2312 case OMPD_target_teams_distribute_parallel_for_simd: 2313 case OMPD_target_teams_distribute_simd: { 2314 // Special processing for flush and depobj clauses. 2315 Token ImplicitTok; 2316 bool ImplicitClauseAllowed = false; 2317 if (DKind == OMPD_flush || DKind == OMPD_depobj) { 2318 ImplicitTok = Tok; 2319 ImplicitClauseAllowed = true; 2320 } 2321 ConsumeToken(); 2322 // Parse directive name of the 'critical' directive if any. 2323 if (DKind == OMPD_critical) { 2324 BalancedDelimiterTracker T(*this, tok::l_paren, 2325 tok::annot_pragma_openmp_end); 2326 if (!T.consumeOpen()) { 2327 if (Tok.isAnyIdentifier()) { 2328 DirName = 2329 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 2330 ConsumeAnyToken(); 2331 } else { 2332 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 2333 } 2334 T.consumeClose(); 2335 } 2336 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 2337 CancelRegion = parseOpenMPDirectiveKind(*this); 2338 if (Tok.isNot(tok::annot_pragma_openmp_end)) 2339 ConsumeToken(); 2340 } 2341 2342 if (isOpenMPLoopDirective(DKind)) 2343 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 2344 if (isOpenMPSimdDirective(DKind)) 2345 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 2346 ParseScope OMPDirectiveScope(this, ScopeFlags); 2347 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 2348 2349 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2350 bool HasImplicitClause = false; 2351 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { 2352 HasImplicitClause = true; 2353 // Push copy of the current token back to stream to properly parse 2354 // pseudo-clause OMPFlushClause or OMPDepobjClause. 2355 PP.EnterToken(Tok, /*IsReinject*/ true); 2356 PP.EnterToken(ImplicitTok, /*IsReinject*/ true); 2357 ConsumeAnyToken(); 2358 } 2359 OpenMPClauseKind CKind = Tok.isAnnotation() 2360 ? OMPC_unknown 2361 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2362 if (HasImplicitClause) { 2363 assert(CKind == OMPC_unknown && "Must be unknown implicit clause."); 2364 if (DKind == OMPD_flush) { 2365 CKind = OMPC_flush; 2366 } else { 2367 assert(DKind == OMPD_depobj && 2368 "Expected flush or depobj directives."); 2369 CKind = OMPC_depobj; 2370 } 2371 } 2372 // No more implicit clauses allowed. 2373 ImplicitClauseAllowed = false; 2374 Actions.StartOpenMPClause(CKind); 2375 HasImplicitClause = false; 2376 OMPClause *Clause = ParseOpenMPClause( 2377 DKind, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2378 FirstClauses[unsigned(CKind)].setInt(true); 2379 if (Clause) { 2380 FirstClauses[unsigned(CKind)].setPointer(Clause); 2381 Clauses.push_back(Clause); 2382 } 2383 2384 // Skip ',' if any. 2385 if (Tok.is(tok::comma)) 2386 ConsumeToken(); 2387 Actions.EndOpenMPClause(); 2388 } 2389 // End location of the directive. 2390 EndLoc = Tok.getLocation(); 2391 // Consume final annot_pragma_openmp_end. 2392 ConsumeAnnotationToken(); 2393 2394 // OpenMP [2.13.8, ordered Construct, Syntax] 2395 // If the depend clause is specified, the ordered construct is a stand-alone 2396 // directive. 2397 if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) { 2398 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2399 ParsedStmtContext()) { 2400 Diag(Loc, diag::err_omp_immediate_directive) 2401 << getOpenMPDirectiveName(DKind) << 1 2402 << getOpenMPClauseName(OMPC_depend); 2403 } 2404 HasAssociatedStatement = false; 2405 } 2406 2407 StmtResult AssociatedStmt; 2408 if (HasAssociatedStatement) { 2409 // The body is a block scope like in Lambdas and Blocks. 2410 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2411 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 2412 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 2413 // should have at least one compound statement scope within it. 2414 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2415 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 2416 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2417 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 2418 DKind == OMPD_target_exit_data) { 2419 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2420 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 2421 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 2422 /*isStmtExpr=*/false)); 2423 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2424 } 2425 Directive = Actions.ActOnOpenMPExecutableDirective( 2426 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 2427 EndLoc); 2428 2429 // Exit scope. 2430 Actions.EndOpenMPDSABlock(Directive.get()); 2431 OMPDirectiveScope.Exit(); 2432 break; 2433 } 2434 case OMPD_declare_simd: 2435 case OMPD_declare_target: 2436 case OMPD_end_declare_target: 2437 case OMPD_requires: 2438 case OMPD_begin_declare_variant: 2439 case OMPD_end_declare_variant: 2440 case OMPD_declare_variant: 2441 Diag(Tok, diag::err_omp_unexpected_directive) 2442 << 1 << getOpenMPDirectiveName(DKind); 2443 SkipUntil(tok::annot_pragma_openmp_end); 2444 break; 2445 case OMPD_unknown: 2446 default: 2447 Diag(Tok, diag::err_omp_unknown_directive); 2448 SkipUntil(tok::annot_pragma_openmp_end); 2449 break; 2450 } 2451 return Directive; 2452 } 2453 2454 // Parses simple list: 2455 // simple-variable-list: 2456 // '(' id-expression {, id-expression} ')' 2457 // 2458 bool Parser::ParseOpenMPSimpleVarList( 2459 OpenMPDirectiveKind Kind, 2460 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 2461 Callback, 2462 bool AllowScopeSpecifier) { 2463 // Parse '('. 2464 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2465 if (T.expectAndConsume(diag::err_expected_lparen_after, 2466 getOpenMPDirectiveName(Kind).data())) 2467 return true; 2468 bool IsCorrect = true; 2469 bool NoIdentIsFound = true; 2470 2471 // Read tokens while ')' or annot_pragma_openmp_end is not found. 2472 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 2473 CXXScopeSpec SS; 2474 UnqualifiedId Name; 2475 // Read var name. 2476 Token PrevTok = Tok; 2477 NoIdentIsFound = false; 2478 2479 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 2480 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 2481 /*ObjectHadErrors=*/false, false)) { 2482 IsCorrect = false; 2483 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2484 StopBeforeMatch); 2485 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, 2486 /*ObjectHadErrors=*/false, false, false, 2487 false, false, nullptr, Name)) { 2488 IsCorrect = false; 2489 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2490 StopBeforeMatch); 2491 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 2492 Tok.isNot(tok::annot_pragma_openmp_end)) { 2493 IsCorrect = false; 2494 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2495 StopBeforeMatch); 2496 Diag(PrevTok.getLocation(), diag::err_expected) 2497 << tok::identifier 2498 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 2499 } else { 2500 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 2501 } 2502 // Consume ','. 2503 if (Tok.is(tok::comma)) { 2504 ConsumeToken(); 2505 } 2506 } 2507 2508 if (NoIdentIsFound) { 2509 Diag(Tok, diag::err_expected) << tok::identifier; 2510 IsCorrect = false; 2511 } 2512 2513 // Parse ')'. 2514 IsCorrect = !T.consumeClose() && IsCorrect; 2515 2516 return !IsCorrect; 2517 } 2518 2519 OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { 2520 SourceLocation Loc = Tok.getLocation(); 2521 ConsumeAnyToken(); 2522 2523 // Parse '('. 2524 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2525 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator")) 2526 return nullptr; 2527 SmallVector<Sema::UsesAllocatorsData, 4> Data; 2528 do { 2529 ExprResult Allocator = ParseCXXIdExpression(); 2530 if (Allocator.isInvalid()) { 2531 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2532 StopBeforeMatch); 2533 break; 2534 } 2535 Sema::UsesAllocatorsData &D = Data.emplace_back(); 2536 D.Allocator = Allocator.get(); 2537 if (Tok.is(tok::l_paren)) { 2538 BalancedDelimiterTracker T(*this, tok::l_paren, 2539 tok::annot_pragma_openmp_end); 2540 T.consumeOpen(); 2541 ExprResult AllocatorTraits = ParseCXXIdExpression(); 2542 T.consumeClose(); 2543 if (AllocatorTraits.isInvalid()) { 2544 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2545 StopBeforeMatch); 2546 break; 2547 } 2548 D.AllocatorTraits = AllocatorTraits.get(); 2549 D.LParenLoc = T.getOpenLocation(); 2550 D.RParenLoc = T.getCloseLocation(); 2551 } 2552 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 2553 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0; 2554 // Parse ',' 2555 if (Tok.is(tok::comma)) 2556 ConsumeAnyToken(); 2557 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); 2558 T.consumeClose(); 2559 return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(), 2560 T.getCloseLocation(), Data); 2561 } 2562 2563 /// Parsing of OpenMP clauses. 2564 /// 2565 /// clause: 2566 /// if-clause | final-clause | num_threads-clause | safelen-clause | 2567 /// default-clause | private-clause | firstprivate-clause | shared-clause 2568 /// | linear-clause | aligned-clause | collapse-clause | 2569 /// lastprivate-clause | reduction-clause | proc_bind-clause | 2570 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 2571 /// mergeable-clause | flush-clause | read-clause | write-clause | 2572 /// update-clause | capture-clause | seq_cst-clause | device-clause | 2573 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 2574 /// thread_limit-clause | priority-clause | grainsize-clause | 2575 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 2576 /// from-clause | is_device_ptr-clause | task_reduction-clause | 2577 /// in_reduction-clause | allocator-clause | allocate-clause | 2578 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | 2579 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause | 2580 /// exclusive-clause | uses_allocators-clause | use_device_addr-clause 2581 /// 2582 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 2583 OpenMPClauseKind CKind, bool FirstClause) { 2584 OMPClauseKind = CKind; 2585 OMPClause *Clause = nullptr; 2586 bool ErrorFound = false; 2587 bool WrongDirective = false; 2588 // Check if clause is allowed for the given directive. 2589 if (CKind != OMPC_unknown && 2590 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 2591 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 2592 << getOpenMPDirectiveName(DKind); 2593 ErrorFound = true; 2594 WrongDirective = true; 2595 } 2596 2597 switch (CKind) { 2598 case OMPC_final: 2599 case OMPC_num_threads: 2600 case OMPC_safelen: 2601 case OMPC_simdlen: 2602 case OMPC_collapse: 2603 case OMPC_ordered: 2604 case OMPC_num_teams: 2605 case OMPC_thread_limit: 2606 case OMPC_priority: 2607 case OMPC_grainsize: 2608 case OMPC_num_tasks: 2609 case OMPC_hint: 2610 case OMPC_allocator: 2611 case OMPC_depobj: 2612 case OMPC_detach: 2613 // OpenMP [2.5, Restrictions] 2614 // At most one num_threads clause can appear on the directive. 2615 // OpenMP [2.8.1, simd construct, Restrictions] 2616 // Only one safelen clause can appear on a simd directive. 2617 // Only one simdlen clause can appear on a simd directive. 2618 // Only one collapse clause can appear on a simd directive. 2619 // OpenMP [2.11.1, task Construct, Restrictions] 2620 // At most one if clause can appear on the directive. 2621 // At most one final clause can appear on the directive. 2622 // OpenMP [teams Construct, Restrictions] 2623 // At most one num_teams clause can appear on the directive. 2624 // At most one thread_limit clause can appear on the directive. 2625 // OpenMP [2.9.1, task Construct, Restrictions] 2626 // At most one priority clause can appear on the directive. 2627 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2628 // At most one grainsize clause can appear on the directive. 2629 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2630 // At most one num_tasks clause can appear on the directive. 2631 // OpenMP [2.11.3, allocate Directive, Restrictions] 2632 // At most one allocator clause can appear on the directive. 2633 // OpenMP 5.0, 2.10.1 task Construct, Restrictions. 2634 // At most one detach clause can appear on the directive. 2635 if (!FirstClause) { 2636 Diag(Tok, diag::err_omp_more_one_clause) 2637 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2638 ErrorFound = true; 2639 } 2640 2641 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 2642 Clause = ParseOpenMPClause(CKind, WrongDirective); 2643 else 2644 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 2645 break; 2646 case OMPC_default: 2647 case OMPC_proc_bind: 2648 case OMPC_atomic_default_mem_order: 2649 case OMPC_order: 2650 // OpenMP [2.14.3.1, Restrictions] 2651 // Only a single default clause may be specified on a parallel, task or 2652 // teams directive. 2653 // OpenMP [2.5, parallel Construct, Restrictions] 2654 // At most one proc_bind clause can appear on the directive. 2655 // OpenMP [5.0, Requires directive, Restrictions] 2656 // At most one atomic_default_mem_order clause can appear 2657 // on the directive 2658 if (!FirstClause && CKind != OMPC_order) { 2659 Diag(Tok, diag::err_omp_more_one_clause) 2660 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2661 ErrorFound = true; 2662 } 2663 2664 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 2665 break; 2666 case OMPC_device: 2667 case OMPC_schedule: 2668 case OMPC_dist_schedule: 2669 case OMPC_defaultmap: 2670 // OpenMP [2.7.1, Restrictions, p. 3] 2671 // Only one schedule clause can appear on a loop directive. 2672 // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 2673 // At most one defaultmap clause can appear on the directive. 2674 // OpenMP 5.0 [2.12.5, target construct, Restrictions] 2675 // At most one device clause can appear on the directive. 2676 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 2677 !FirstClause) { 2678 Diag(Tok, diag::err_omp_more_one_clause) 2679 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2680 ErrorFound = true; 2681 } 2682 LLVM_FALLTHROUGH; 2683 case OMPC_if: 2684 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); 2685 break; 2686 case OMPC_nowait: 2687 case OMPC_untied: 2688 case OMPC_mergeable: 2689 case OMPC_read: 2690 case OMPC_write: 2691 case OMPC_capture: 2692 case OMPC_seq_cst: 2693 case OMPC_acq_rel: 2694 case OMPC_acquire: 2695 case OMPC_release: 2696 case OMPC_relaxed: 2697 case OMPC_threads: 2698 case OMPC_simd: 2699 case OMPC_nogroup: 2700 case OMPC_unified_address: 2701 case OMPC_unified_shared_memory: 2702 case OMPC_reverse_offload: 2703 case OMPC_dynamic_allocators: 2704 case OMPC_destroy: 2705 // OpenMP [2.7.1, Restrictions, p. 9] 2706 // Only one ordered clause can appear on a loop directive. 2707 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 2708 // Only one nowait clause can appear on a for directive. 2709 // OpenMP [5.0, Requires directive, Restrictions] 2710 // Each of the requires clauses can appear at most once on the directive. 2711 if (!FirstClause) { 2712 Diag(Tok, diag::err_omp_more_one_clause) 2713 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2714 ErrorFound = true; 2715 } 2716 2717 Clause = ParseOpenMPClause(CKind, WrongDirective); 2718 break; 2719 case OMPC_update: 2720 if (!FirstClause) { 2721 Diag(Tok, diag::err_omp_more_one_clause) 2722 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2723 ErrorFound = true; 2724 } 2725 2726 Clause = (DKind == OMPD_depobj) 2727 ? ParseOpenMPSimpleClause(CKind, WrongDirective) 2728 : ParseOpenMPClause(CKind, WrongDirective); 2729 break; 2730 case OMPC_private: 2731 case OMPC_firstprivate: 2732 case OMPC_lastprivate: 2733 case OMPC_shared: 2734 case OMPC_reduction: 2735 case OMPC_task_reduction: 2736 case OMPC_in_reduction: 2737 case OMPC_linear: 2738 case OMPC_aligned: 2739 case OMPC_copyin: 2740 case OMPC_copyprivate: 2741 case OMPC_flush: 2742 case OMPC_depend: 2743 case OMPC_map: 2744 case OMPC_to: 2745 case OMPC_from: 2746 case OMPC_use_device_ptr: 2747 case OMPC_use_device_addr: 2748 case OMPC_is_device_ptr: 2749 case OMPC_allocate: 2750 case OMPC_nontemporal: 2751 case OMPC_inclusive: 2752 case OMPC_exclusive: 2753 case OMPC_affinity: 2754 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 2755 break; 2756 case OMPC_uses_allocators: 2757 Clause = ParseOpenMPUsesAllocatorClause(DKind); 2758 break; 2759 case OMPC_device_type: 2760 case OMPC_unknown: 2761 skipUntilPragmaOpenMPEnd(DKind); 2762 break; 2763 case OMPC_threadprivate: 2764 case OMPC_uniform: 2765 case OMPC_match: 2766 if (!WrongDirective) 2767 Diag(Tok, diag::err_omp_unexpected_clause) 2768 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 2769 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 2770 break; 2771 default: 2772 break; 2773 } 2774 return ErrorFound ? nullptr : Clause; 2775 } 2776 2777 /// Parses simple expression in parens for single-expression clauses of OpenMP 2778 /// constructs. 2779 /// \param RLoc Returned location of right paren. 2780 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 2781 SourceLocation &RLoc, 2782 bool IsAddressOfOperand) { 2783 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2784 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 2785 return ExprError(); 2786 2787 SourceLocation ELoc = Tok.getLocation(); 2788 ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand, 2789 NotTypeCast)); 2790 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 2791 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2792 2793 // Parse ')'. 2794 RLoc = Tok.getLocation(); 2795 if (!T.consumeClose()) 2796 RLoc = T.getCloseLocation(); 2797 2798 return Val; 2799 } 2800 2801 /// Parsing of OpenMP clauses with single expressions like 'final', 2802 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 2803 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or 2804 /// 'detach'. 2805 /// 2806 /// final-clause: 2807 /// 'final' '(' expression ')' 2808 /// 2809 /// num_threads-clause: 2810 /// 'num_threads' '(' expression ')' 2811 /// 2812 /// safelen-clause: 2813 /// 'safelen' '(' expression ')' 2814 /// 2815 /// simdlen-clause: 2816 /// 'simdlen' '(' expression ')' 2817 /// 2818 /// collapse-clause: 2819 /// 'collapse' '(' expression ')' 2820 /// 2821 /// priority-clause: 2822 /// 'priority' '(' expression ')' 2823 /// 2824 /// grainsize-clause: 2825 /// 'grainsize' '(' expression ')' 2826 /// 2827 /// num_tasks-clause: 2828 /// 'num_tasks' '(' expression ')' 2829 /// 2830 /// hint-clause: 2831 /// 'hint' '(' expression ')' 2832 /// 2833 /// allocator-clause: 2834 /// 'allocator' '(' expression ')' 2835 /// 2836 /// detach-clause: 2837 /// 'detach' '(' event-handler-expression ')' 2838 /// 2839 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 2840 bool ParseOnly) { 2841 SourceLocation Loc = ConsumeToken(); 2842 SourceLocation LLoc = Tok.getLocation(); 2843 SourceLocation RLoc; 2844 2845 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 2846 2847 if (Val.isInvalid()) 2848 return nullptr; 2849 2850 if (ParseOnly) 2851 return nullptr; 2852 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 2853 } 2854 2855 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 2856 /// 2857 /// default-clause: 2858 /// 'default' '(' 'none' | 'shared' | 'firstprivate' ')' 2859 /// 2860 /// proc_bind-clause: 2861 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' 2862 /// 2863 /// update-clause: 2864 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')' 2865 /// 2866 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 2867 bool ParseOnly) { 2868 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 2869 if (!Val || ParseOnly) 2870 return nullptr; 2871 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default && 2872 static_cast<DefaultKind>(Val.getValue().Type) == 2873 OMP_DEFAULT_firstprivate) { 2874 Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa) 2875 << getOpenMPClauseName(OMPC_firstprivate) 2876 << getOpenMPClauseName(OMPC_default) << "5.1"; 2877 return nullptr; 2878 } 2879 return Actions.ActOnOpenMPSimpleClause( 2880 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, 2881 Val.getValue().Loc, Val.getValue().RLoc); 2882 } 2883 2884 /// Parsing of OpenMP clauses like 'ordered'. 2885 /// 2886 /// ordered-clause: 2887 /// 'ordered' 2888 /// 2889 /// nowait-clause: 2890 /// 'nowait' 2891 /// 2892 /// untied-clause: 2893 /// 'untied' 2894 /// 2895 /// mergeable-clause: 2896 /// 'mergeable' 2897 /// 2898 /// read-clause: 2899 /// 'read' 2900 /// 2901 /// threads-clause: 2902 /// 'threads' 2903 /// 2904 /// simd-clause: 2905 /// 'simd' 2906 /// 2907 /// nogroup-clause: 2908 /// 'nogroup' 2909 /// 2910 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 2911 SourceLocation Loc = Tok.getLocation(); 2912 ConsumeAnyToken(); 2913 2914 if (ParseOnly) 2915 return nullptr; 2916 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 2917 } 2918 2919 /// Parsing of OpenMP clauses with single expressions and some additional 2920 /// argument like 'schedule' or 'dist_schedule'. 2921 /// 2922 /// schedule-clause: 2923 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 2924 /// ')' 2925 /// 2926 /// if-clause: 2927 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 2928 /// 2929 /// defaultmap: 2930 /// 'defaultmap' '(' modifier [ ':' kind ] ')' 2931 /// 2932 /// device-clause: 2933 /// 'device' '(' [ device-modifier ':' ] expression ')' 2934 /// 2935 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, 2936 OpenMPClauseKind Kind, 2937 bool ParseOnly) { 2938 SourceLocation Loc = ConsumeToken(); 2939 SourceLocation DelimLoc; 2940 // Parse '('. 2941 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2942 if (T.expectAndConsume(diag::err_expected_lparen_after, 2943 getOpenMPClauseName(Kind).data())) 2944 return nullptr; 2945 2946 ExprResult Val; 2947 SmallVector<unsigned, 4> Arg; 2948 SmallVector<SourceLocation, 4> KLoc; 2949 if (Kind == OMPC_schedule) { 2950 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 2951 Arg.resize(NumberOfElements); 2952 KLoc.resize(NumberOfElements); 2953 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 2954 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 2955 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 2956 unsigned KindModifier = getOpenMPSimpleClauseType( 2957 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2958 getLangOpts().OpenMP); 2959 if (KindModifier > OMPC_SCHEDULE_unknown) { 2960 // Parse 'modifier' 2961 Arg[Modifier1] = KindModifier; 2962 KLoc[Modifier1] = Tok.getLocation(); 2963 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2964 Tok.isNot(tok::annot_pragma_openmp_end)) 2965 ConsumeAnyToken(); 2966 if (Tok.is(tok::comma)) { 2967 // Parse ',' 'modifier' 2968 ConsumeAnyToken(); 2969 KindModifier = getOpenMPSimpleClauseType( 2970 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2971 getLangOpts().OpenMP); 2972 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 2973 ? KindModifier 2974 : (unsigned)OMPC_SCHEDULE_unknown; 2975 KLoc[Modifier2] = Tok.getLocation(); 2976 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2977 Tok.isNot(tok::annot_pragma_openmp_end)) 2978 ConsumeAnyToken(); 2979 } 2980 // Parse ':' 2981 if (Tok.is(tok::colon)) 2982 ConsumeAnyToken(); 2983 else 2984 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 2985 KindModifier = getOpenMPSimpleClauseType( 2986 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2987 getLangOpts().OpenMP); 2988 } 2989 Arg[ScheduleKind] = KindModifier; 2990 KLoc[ScheduleKind] = Tok.getLocation(); 2991 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2992 Tok.isNot(tok::annot_pragma_openmp_end)) 2993 ConsumeAnyToken(); 2994 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 2995 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 2996 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 2997 Tok.is(tok::comma)) 2998 DelimLoc = ConsumeAnyToken(); 2999 } else if (Kind == OMPC_dist_schedule) { 3000 Arg.push_back(getOpenMPSimpleClauseType( 3001 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 3002 getLangOpts().OpenMP)); 3003 KLoc.push_back(Tok.getLocation()); 3004 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3005 Tok.isNot(tok::annot_pragma_openmp_end)) 3006 ConsumeAnyToken(); 3007 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 3008 DelimLoc = ConsumeAnyToken(); 3009 } else if (Kind == OMPC_defaultmap) { 3010 // Get a defaultmap modifier 3011 unsigned Modifier = getOpenMPSimpleClauseType( 3012 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 3013 getLangOpts().OpenMP); 3014 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 3015 // pointer 3016 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 3017 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 3018 Arg.push_back(Modifier); 3019 KLoc.push_back(Tok.getLocation()); 3020 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3021 Tok.isNot(tok::annot_pragma_openmp_end)) 3022 ConsumeAnyToken(); 3023 // Parse ':' 3024 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) { 3025 if (Tok.is(tok::colon)) 3026 ConsumeAnyToken(); 3027 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 3028 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 3029 // Get a defaultmap kind 3030 Arg.push_back(getOpenMPSimpleClauseType( 3031 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 3032 getLangOpts().OpenMP)); 3033 KLoc.push_back(Tok.getLocation()); 3034 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3035 Tok.isNot(tok::annot_pragma_openmp_end)) 3036 ConsumeAnyToken(); 3037 } else { 3038 Arg.push_back(OMPC_DEFAULTMAP_unknown); 3039 KLoc.push_back(SourceLocation()); 3040 } 3041 } else if (Kind == OMPC_device) { 3042 // Only target executable directives support extended device construct. 3043 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 && 3044 NextToken().is(tok::colon)) { 3045 // Parse optional <device modifier> ':' 3046 Arg.push_back(getOpenMPSimpleClauseType( 3047 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 3048 getLangOpts().OpenMP)); 3049 KLoc.push_back(Tok.getLocation()); 3050 ConsumeAnyToken(); 3051 // Parse ':' 3052 ConsumeAnyToken(); 3053 } else { 3054 Arg.push_back(OMPC_DEVICE_unknown); 3055 KLoc.emplace_back(); 3056 } 3057 } else { 3058 assert(Kind == OMPC_if); 3059 KLoc.push_back(Tok.getLocation()); 3060 TentativeParsingAction TPA(*this); 3061 auto DK = parseOpenMPDirectiveKind(*this); 3062 Arg.push_back(DK); 3063 if (DK != OMPD_unknown) { 3064 ConsumeToken(); 3065 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 3066 TPA.Commit(); 3067 DelimLoc = ConsumeToken(); 3068 } else { 3069 TPA.Revert(); 3070 Arg.back() = unsigned(OMPD_unknown); 3071 } 3072 } else { 3073 TPA.Revert(); 3074 } 3075 } 3076 3077 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 3078 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 3079 Kind == OMPC_if || Kind == OMPC_device; 3080 if (NeedAnExpression) { 3081 SourceLocation ELoc = Tok.getLocation(); 3082 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 3083 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 3084 Val = 3085 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3086 } 3087 3088 // Parse ')'. 3089 SourceLocation RLoc = Tok.getLocation(); 3090 if (!T.consumeClose()) 3091 RLoc = T.getCloseLocation(); 3092 3093 if (NeedAnExpression && Val.isInvalid()) 3094 return nullptr; 3095 3096 if (ParseOnly) 3097 return nullptr; 3098 return Actions.ActOnOpenMPSingleExprWithArgClause( 3099 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 3100 } 3101 3102 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 3103 UnqualifiedId &ReductionId) { 3104 if (ReductionIdScopeSpec.isEmpty()) { 3105 auto OOK = OO_None; 3106 switch (P.getCurToken().getKind()) { 3107 case tok::plus: 3108 OOK = OO_Plus; 3109 break; 3110 case tok::minus: 3111 OOK = OO_Minus; 3112 break; 3113 case tok::star: 3114 OOK = OO_Star; 3115 break; 3116 case tok::amp: 3117 OOK = OO_Amp; 3118 break; 3119 case tok::pipe: 3120 OOK = OO_Pipe; 3121 break; 3122 case tok::caret: 3123 OOK = OO_Caret; 3124 break; 3125 case tok::ampamp: 3126 OOK = OO_AmpAmp; 3127 break; 3128 case tok::pipepipe: 3129 OOK = OO_PipePipe; 3130 break; 3131 default: 3132 break; 3133 } 3134 if (OOK != OO_None) { 3135 SourceLocation OpLoc = P.ConsumeToken(); 3136 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 3137 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 3138 return false; 3139 } 3140 } 3141 return P.ParseUnqualifiedId( 3142 ReductionIdScopeSpec, /*ObjectType=*/nullptr, 3143 /*ObjectHadErrors=*/false, /*EnteringContext*/ false, 3144 /*AllowDestructorName*/ false, 3145 /*AllowConstructorName*/ false, 3146 /*AllowDeductionGuide*/ false, nullptr, ReductionId); 3147 } 3148 3149 /// Checks if the token is a valid map-type-modifier. 3150 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses. 3151 static OpenMPMapModifierKind isMapModifier(Parser &P) { 3152 Token Tok = P.getCurToken(); 3153 if (!Tok.is(tok::identifier)) 3154 return OMPC_MAP_MODIFIER_unknown; 3155 3156 Preprocessor &PP = P.getPreprocessor(); 3157 OpenMPMapModifierKind TypeModifier = 3158 static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType( 3159 OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP)); 3160 return TypeModifier; 3161 } 3162 3163 /// Parse the mapper modifier in map, to, and from clauses. 3164 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 3165 // Parse '('. 3166 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 3167 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 3168 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3169 StopBeforeMatch); 3170 return true; 3171 } 3172 // Parse mapper-identifier 3173 if (getLangOpts().CPlusPlus) 3174 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3175 /*ObjectType=*/nullptr, 3176 /*ObjectHadErrors=*/false, 3177 /*EnteringContext=*/false); 3178 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 3179 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 3180 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3181 StopBeforeMatch); 3182 return true; 3183 } 3184 auto &DeclNames = Actions.getASTContext().DeclarationNames; 3185 Data.ReductionOrMapperId = DeclarationNameInfo( 3186 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 3187 ConsumeToken(); 3188 // Parse ')'. 3189 return T.consumeClose(); 3190 } 3191 3192 /// Parse map-type-modifiers in map clause. 3193 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3194 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) | 3195 /// present 3196 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 3197 while (getCurToken().isNot(tok::colon)) { 3198 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 3199 if (TypeModifier == OMPC_MAP_MODIFIER_always || 3200 TypeModifier == OMPC_MAP_MODIFIER_close || 3201 TypeModifier == OMPC_MAP_MODIFIER_present) { 3202 Data.MapTypeModifiers.push_back(TypeModifier); 3203 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3204 ConsumeToken(); 3205 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 3206 Data.MapTypeModifiers.push_back(TypeModifier); 3207 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3208 ConsumeToken(); 3209 if (parseMapperModifier(Data)) 3210 return true; 3211 } else { 3212 // For the case of unknown map-type-modifier or a map-type. 3213 // Map-type is followed by a colon; the function returns when it 3214 // encounters a token followed by a colon. 3215 if (Tok.is(tok::comma)) { 3216 Diag(Tok, diag::err_omp_map_type_modifier_missing); 3217 ConsumeToken(); 3218 continue; 3219 } 3220 // Potential map-type token as it is followed by a colon. 3221 if (PP.LookAhead(0).is(tok::colon)) 3222 return false; 3223 Diag(Tok, diag::err_omp_unknown_map_type_modifier) 3224 << (getLangOpts().OpenMP >= 51 ? 1 : 0); 3225 ConsumeToken(); 3226 } 3227 if (getCurToken().is(tok::comma)) 3228 ConsumeToken(); 3229 } 3230 return false; 3231 } 3232 3233 /// Checks if the token is a valid map-type. 3234 /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses. 3235 static OpenMPMapClauseKind isMapType(Parser &P) { 3236 Token Tok = P.getCurToken(); 3237 // The map-type token can be either an identifier or the C++ delete keyword. 3238 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 3239 return OMPC_MAP_unknown; 3240 Preprocessor &PP = P.getPreprocessor(); 3241 OpenMPMapClauseKind MapType = 3242 static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 3243 OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP)); 3244 return MapType; 3245 } 3246 3247 /// Parse map-type in map clause. 3248 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3249 /// where, map-type ::= to | from | tofrom | alloc | release | delete 3250 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 3251 Token Tok = P.getCurToken(); 3252 if (Tok.is(tok::colon)) { 3253 P.Diag(Tok, diag::err_omp_map_type_missing); 3254 return; 3255 } 3256 Data.ExtraModifier = isMapType(P); 3257 if (Data.ExtraModifier == OMPC_MAP_unknown) 3258 P.Diag(Tok, diag::err_omp_unknown_map_type); 3259 P.ConsumeToken(); 3260 } 3261 3262 /// Parses simple expression in parens for single-expression clauses of OpenMP 3263 /// constructs. 3264 ExprResult Parser::ParseOpenMPIteratorsExpr() { 3265 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" && 3266 "Expected 'iterator' token."); 3267 SourceLocation IteratorKwLoc = ConsumeToken(); 3268 3269 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3270 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator")) 3271 return ExprError(); 3272 3273 SourceLocation LLoc = T.getOpenLocation(); 3274 SmallVector<Sema::OMPIteratorData, 4> Data; 3275 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 3276 // Check if the type parsing is required. 3277 ParsedType IteratorType; 3278 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) { 3279 // identifier '=' is not found - parse type. 3280 TypeResult TR = ParseTypeName(); 3281 if (TR.isInvalid()) { 3282 T.skipToEnd(); 3283 return ExprError(); 3284 } 3285 IteratorType = TR.get(); 3286 } 3287 3288 // Parse identifier. 3289 IdentifierInfo *II = nullptr; 3290 SourceLocation IdLoc; 3291 if (Tok.is(tok::identifier)) { 3292 II = Tok.getIdentifierInfo(); 3293 IdLoc = ConsumeToken(); 3294 } else { 3295 Diag(Tok, diag::err_expected_unqualified_id) << 0; 3296 } 3297 3298 // Parse '='. 3299 SourceLocation AssignLoc; 3300 if (Tok.is(tok::equal)) 3301 AssignLoc = ConsumeToken(); 3302 else 3303 Diag(Tok, diag::err_omp_expected_equal_in_iterator); 3304 3305 // Parse range-specification - <begin> ':' <end> [ ':' <step> ] 3306 ColonProtectionRAIIObject ColonRAII(*this); 3307 // Parse <begin> 3308 SourceLocation Loc = Tok.getLocation(); 3309 ExprResult LHS = ParseCastExpression(AnyCastExpr); 3310 ExprResult Begin = Actions.CorrectDelayedTyposInExpr( 3311 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3312 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc, 3313 /*DiscardedValue=*/false); 3314 // Parse ':'. 3315 SourceLocation ColonLoc; 3316 if (Tok.is(tok::colon)) 3317 ColonLoc = ConsumeToken(); 3318 3319 // Parse <end> 3320 Loc = Tok.getLocation(); 3321 LHS = ParseCastExpression(AnyCastExpr); 3322 ExprResult End = Actions.CorrectDelayedTyposInExpr( 3323 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3324 End = Actions.ActOnFinishFullExpr(End.get(), Loc, 3325 /*DiscardedValue=*/false); 3326 3327 SourceLocation SecColonLoc; 3328 ExprResult Step; 3329 // Parse optional step. 3330 if (Tok.is(tok::colon)) { 3331 // Parse ':' 3332 SecColonLoc = ConsumeToken(); 3333 // Parse <step> 3334 Loc = Tok.getLocation(); 3335 LHS = ParseCastExpression(AnyCastExpr); 3336 Step = Actions.CorrectDelayedTyposInExpr( 3337 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3338 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc, 3339 /*DiscardedValue=*/false); 3340 } 3341 3342 // Parse ',' or ')' 3343 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 3344 Diag(Tok, diag::err_omp_expected_punc_after_iterator); 3345 if (Tok.is(tok::comma)) 3346 ConsumeToken(); 3347 3348 Sema::OMPIteratorData &D = Data.emplace_back(); 3349 D.DeclIdent = II; 3350 D.DeclIdentLoc = IdLoc; 3351 D.Type = IteratorType; 3352 D.AssignLoc = AssignLoc; 3353 D.ColonLoc = ColonLoc; 3354 D.SecColonLoc = SecColonLoc; 3355 D.Range.Begin = Begin.get(); 3356 D.Range.End = End.get(); 3357 D.Range.Step = Step.get(); 3358 } 3359 3360 // Parse ')'. 3361 SourceLocation RLoc = Tok.getLocation(); 3362 if (!T.consumeClose()) 3363 RLoc = T.getCloseLocation(); 3364 3365 return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc, 3366 Data); 3367 } 3368 3369 /// Parses clauses with list. 3370 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 3371 OpenMPClauseKind Kind, 3372 SmallVectorImpl<Expr *> &Vars, 3373 OpenMPVarListDataTy &Data) { 3374 UnqualifiedId UnqualifiedReductionId; 3375 bool InvalidReductionId = false; 3376 bool IsInvalidMapperModifier = false; 3377 3378 // Parse '('. 3379 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3380 if (T.expectAndConsume(diag::err_expected_lparen_after, 3381 getOpenMPClauseName(Kind).data())) 3382 return true; 3383 3384 bool HasIterator = false; 3385 bool NeedRParenForLinear = false; 3386 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 3387 tok::annot_pragma_openmp_end); 3388 // Handle reduction-identifier for reduction clause. 3389 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 3390 Kind == OMPC_in_reduction) { 3391 Data.ExtraModifier = OMPC_REDUCTION_unknown; 3392 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 && 3393 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) && 3394 NextToken().is(tok::comma)) { 3395 // Parse optional reduction modifier. 3396 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), 3397 getLangOpts().OpenMP); 3398 Data.ExtraModifierLoc = Tok.getLocation(); 3399 ConsumeToken(); 3400 assert(Tok.is(tok::comma) && "Expected comma."); 3401 (void)ConsumeToken(); 3402 } 3403 ColonProtectionRAIIObject ColonRAII(*this); 3404 if (getLangOpts().CPlusPlus) 3405 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3406 /*ObjectType=*/nullptr, 3407 /*ObjectHadErrors=*/false, 3408 /*EnteringContext=*/false); 3409 InvalidReductionId = ParseReductionId( 3410 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 3411 if (InvalidReductionId) { 3412 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3413 StopBeforeMatch); 3414 } 3415 if (Tok.is(tok::colon)) 3416 Data.ColonLoc = ConsumeToken(); 3417 else 3418 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 3419 if (!InvalidReductionId) 3420 Data.ReductionOrMapperId = 3421 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 3422 } else if (Kind == OMPC_depend) { 3423 if (getLangOpts().OpenMP >= 50) { 3424 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { 3425 // Handle optional dependence modifier. 3426 // iterator(iterators-definition) 3427 // where iterators-definition is iterator-specifier [, 3428 // iterators-definition ] 3429 // where iterator-specifier is [ iterator-type ] identifier = 3430 // range-specification 3431 HasIterator = true; 3432 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 3433 ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); 3434 Data.DepModOrTailExpr = IteratorRes.get(); 3435 // Parse ',' 3436 ExpectAndConsume(tok::comma); 3437 } 3438 } 3439 // Handle dependency type for depend clause. 3440 ColonProtectionRAIIObject ColonRAII(*this); 3441 Data.ExtraModifier = getOpenMPSimpleClauseType( 3442 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 3443 getLangOpts().OpenMP); 3444 Data.ExtraModifierLoc = Tok.getLocation(); 3445 if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 3446 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3447 StopBeforeMatch); 3448 } else { 3449 ConsumeToken(); 3450 // Special processing for depend(source) clause. 3451 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 3452 // Parse ')'. 3453 T.consumeClose(); 3454 return false; 3455 } 3456 } 3457 if (Tok.is(tok::colon)) { 3458 Data.ColonLoc = ConsumeToken(); 3459 } else { 3460 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 3461 : diag::warn_pragma_expected_colon) 3462 << "dependency type"; 3463 } 3464 } else if (Kind == OMPC_linear) { 3465 // Try to parse modifier if any. 3466 Data.ExtraModifier = OMPC_LINEAR_val; 3467 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 3468 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), 3469 getLangOpts().OpenMP); 3470 Data.ExtraModifierLoc = ConsumeToken(); 3471 LinearT.consumeOpen(); 3472 NeedRParenForLinear = true; 3473 } 3474 } else if (Kind == OMPC_lastprivate) { 3475 // Try to parse modifier if any. 3476 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 3477 // Conditional modifier allowed only in OpenMP 5.0 and not supported in 3478 // distribute and taskloop based directives. 3479 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 3480 !isOpenMPTaskLoopDirective(DKind)) && 3481 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 3482 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), 3483 getLangOpts().OpenMP); 3484 Data.ExtraModifierLoc = Tok.getLocation(); 3485 ConsumeToken(); 3486 assert(Tok.is(tok::colon) && "Expected colon."); 3487 Data.ColonLoc = ConsumeToken(); 3488 } 3489 } else if (Kind == OMPC_map) { 3490 // Handle map type for map clause. 3491 ColonProtectionRAIIObject ColonRAII(*this); 3492 3493 // The first identifier may be a list item, a map-type or a 3494 // map-type-modifier. The map-type can also be delete which has the same 3495 // spelling of the C++ delete keyword. 3496 Data.ExtraModifier = OMPC_MAP_unknown; 3497 Data.ExtraModifierLoc = Tok.getLocation(); 3498 3499 // Check for presence of a colon in the map clause. 3500 TentativeParsingAction TPA(*this); 3501 bool ColonPresent = false; 3502 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3503 StopBeforeMatch)) { 3504 if (Tok.is(tok::colon)) 3505 ColonPresent = true; 3506 } 3507 TPA.Revert(); 3508 // Only parse map-type-modifier[s] and map-type if a colon is present in 3509 // the map clause. 3510 if (ColonPresent) { 3511 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 3512 if (!IsInvalidMapperModifier) 3513 parseMapType(*this, Data); 3514 else 3515 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 3516 } 3517 if (Data.ExtraModifier == OMPC_MAP_unknown) { 3518 Data.ExtraModifier = OMPC_MAP_tofrom; 3519 Data.IsMapTypeImplicit = true; 3520 } 3521 3522 if (Tok.is(tok::colon)) 3523 Data.ColonLoc = ConsumeToken(); 3524 } else if (Kind == OMPC_to || Kind == OMPC_from) { 3525 while (Tok.is(tok::identifier)) { 3526 auto Modifier = 3527 static_cast<OpenMPMotionModifierKind>(getOpenMPSimpleClauseType( 3528 Kind, PP.getSpelling(Tok), getLangOpts().OpenMP)); 3529 if (Modifier == OMPC_MOTION_MODIFIER_unknown) 3530 break; 3531 Data.MotionModifiers.push_back(Modifier); 3532 Data.MotionModifiersLoc.push_back(Tok.getLocation()); 3533 ConsumeToken(); 3534 if (Modifier == OMPC_MOTION_MODIFIER_mapper) { 3535 IsInvalidMapperModifier = parseMapperModifier(Data); 3536 if (IsInvalidMapperModifier) 3537 break; 3538 } 3539 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers. 3540 if (getLangOpts().OpenMP < 51) 3541 break; 3542 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'. 3543 // TODO: Is that intentional? 3544 if (Tok.is(tok::comma)) 3545 ConsumeToken(); 3546 } 3547 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) { 3548 if (!IsInvalidMapperModifier) { 3549 if (getLangOpts().OpenMP < 51) 3550 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 3551 else 3552 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier"; 3553 } 3554 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3555 StopBeforeMatch); 3556 } 3557 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is 3558 // that intentional? 3559 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) && 3560 Tok.is(tok::colon)) 3561 Data.ColonLoc = ConsumeToken(); 3562 } else if (Kind == OMPC_allocate || 3563 (Kind == OMPC_affinity && Tok.is(tok::identifier) && 3564 PP.getSpelling(Tok) == "iterator")) { 3565 // Handle optional allocator expression followed by colon delimiter. 3566 ColonProtectionRAIIObject ColonRAII(*this); 3567 TentativeParsingAction TPA(*this); 3568 // OpenMP 5.0, 2.10.1, task Construct. 3569 // where aff-modifier is one of the following: 3570 // iterator(iterators-definition) 3571 ExprResult Tail; 3572 if (Kind == OMPC_allocate) { 3573 Tail = ParseAssignmentExpression(); 3574 } else { 3575 HasIterator = true; 3576 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 3577 Tail = ParseOpenMPIteratorsExpr(); 3578 } 3579 Tail = Actions.CorrectDelayedTyposInExpr(Tail); 3580 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 3581 /*DiscardedValue=*/false); 3582 if (Tail.isUsable()) { 3583 if (Tok.is(tok::colon)) { 3584 Data.DepModOrTailExpr = Tail.get(); 3585 Data.ColonLoc = ConsumeToken(); 3586 TPA.Commit(); 3587 } else { 3588 // Colon not found, parse only list of variables. 3589 TPA.Revert(); 3590 } 3591 } else { 3592 // Parsing was unsuccessfull, revert and skip to the end of clause or 3593 // directive. 3594 TPA.Revert(); 3595 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3596 StopBeforeMatch); 3597 } 3598 } 3599 3600 bool IsComma = 3601 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 3602 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 3603 (Kind == OMPC_reduction && !InvalidReductionId) || 3604 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 3605 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown); 3606 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 3607 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 3608 Tok.isNot(tok::annot_pragma_openmp_end))) { 3609 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); 3610 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 3611 // Parse variable 3612 ExprResult VarExpr = 3613 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 3614 if (VarExpr.isUsable()) { 3615 Vars.push_back(VarExpr.get()); 3616 } else { 3617 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3618 StopBeforeMatch); 3619 } 3620 // Skip ',' if any 3621 IsComma = Tok.is(tok::comma); 3622 if (IsComma) 3623 ConsumeToken(); 3624 else if (Tok.isNot(tok::r_paren) && 3625 Tok.isNot(tok::annot_pragma_openmp_end) && 3626 (!MayHaveTail || Tok.isNot(tok::colon))) 3627 Diag(Tok, diag::err_omp_expected_punc) 3628 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 3629 : getOpenMPClauseName(Kind)) 3630 << (Kind == OMPC_flush); 3631 } 3632 3633 // Parse ')' for linear clause with modifier. 3634 if (NeedRParenForLinear) 3635 LinearT.consumeClose(); 3636 3637 // Parse ':' linear-step (or ':' alignment). 3638 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 3639 if (MustHaveTail) { 3640 Data.ColonLoc = Tok.getLocation(); 3641 SourceLocation ELoc = ConsumeToken(); 3642 ExprResult Tail = ParseAssignmentExpression(); 3643 Tail = 3644 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 3645 if (Tail.isUsable()) 3646 Data.DepModOrTailExpr = Tail.get(); 3647 else 3648 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3649 StopBeforeMatch); 3650 } 3651 3652 // Parse ')'. 3653 Data.RLoc = Tok.getLocation(); 3654 if (!T.consumeClose()) 3655 Data.RLoc = T.getCloseLocation(); 3656 // Exit from scope when the iterator is used in depend clause. 3657 if (HasIterator) 3658 ExitScope(); 3659 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 3660 (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || 3661 IsInvalidMapperModifier; 3662 } 3663 3664 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 3665 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction', 3666 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'. 3667 /// 3668 /// private-clause: 3669 /// 'private' '(' list ')' 3670 /// firstprivate-clause: 3671 /// 'firstprivate' '(' list ')' 3672 /// lastprivate-clause: 3673 /// 'lastprivate' '(' list ')' 3674 /// shared-clause: 3675 /// 'shared' '(' list ')' 3676 /// linear-clause: 3677 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 3678 /// aligned-clause: 3679 /// 'aligned' '(' list [ ':' alignment ] ')' 3680 /// reduction-clause: 3681 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')' 3682 /// task_reduction-clause: 3683 /// 'task_reduction' '(' reduction-identifier ':' list ')' 3684 /// in_reduction-clause: 3685 /// 'in_reduction' '(' reduction-identifier ':' list ')' 3686 /// copyprivate-clause: 3687 /// 'copyprivate' '(' list ')' 3688 /// flush-clause: 3689 /// 'flush' '(' list ')' 3690 /// depend-clause: 3691 /// 'depend' '(' in | out | inout : list | source ')' 3692 /// map-clause: 3693 /// 'map' '(' [ [ always [,] ] [ close [,] ] 3694 /// [ mapper '(' mapper-identifier ')' [,] ] 3695 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 3696 /// to-clause: 3697 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 3698 /// from-clause: 3699 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 3700 /// use_device_ptr-clause: 3701 /// 'use_device_ptr' '(' list ')' 3702 /// use_device_addr-clause: 3703 /// 'use_device_addr' '(' list ')' 3704 /// is_device_ptr-clause: 3705 /// 'is_device_ptr' '(' list ')' 3706 /// allocate-clause: 3707 /// 'allocate' '(' [ allocator ':' ] list ')' 3708 /// nontemporal-clause: 3709 /// 'nontemporal' '(' list ')' 3710 /// inclusive-clause: 3711 /// 'inclusive' '(' list ')' 3712 /// exclusive-clause: 3713 /// 'exclusive' '(' list ')' 3714 /// 3715 /// For 'linear' clause linear-list may have the following forms: 3716 /// list 3717 /// modifier(list) 3718 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 3719 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 3720 OpenMPClauseKind Kind, 3721 bool ParseOnly) { 3722 SourceLocation Loc = Tok.getLocation(); 3723 SourceLocation LOpen = ConsumeToken(); 3724 SmallVector<Expr *, 4> Vars; 3725 OpenMPVarListDataTy Data; 3726 3727 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 3728 return nullptr; 3729 3730 if (ParseOnly) 3731 return nullptr; 3732 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 3733 return Actions.ActOnOpenMPVarListClause( 3734 Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc, 3735 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 3736 Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 3737 Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers, 3738 Data.MotionModifiersLoc); 3739 } 3740 3741