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 auto IsMatchExtension = [](OMPTraitProperty &TP) { 939 return (TP.Kind == 940 llvm::omp::TraitProperty::implementation_extension_match_all || 941 TP.Kind == 942 llvm::omp::TraitProperty::implementation_extension_match_any || 943 TP.Kind == 944 llvm::omp::TraitProperty::implementation_extension_match_none); 945 }; 946 947 if (IsMatchExtension(TIProperty)) { 948 for (OMPTraitProperty &SeenProp : TISelector.Properties) 949 if (IsMatchExtension(SeenProp)) { 950 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension); 951 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName( 952 SeenProp.Kind, SeenProp.RawString); 953 SourceLocation SeenLoc = Seen[SeenName]; 954 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here) 955 << CONTEXT_TRAIT_LVL << SeenName; 956 return false; 957 } 958 return true; 959 } 960 961 llvm_unreachable("Unknown extension property!"); 962 } 963 964 void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector, 965 llvm::omp::TraitSet Set, 966 llvm::StringMap<SourceLocation> &Seen) { 967 assert(TISelector.Kind != TraitSelector::user_condition && 968 "User conditions are special properties not handled here!"); 969 970 SourceLocation PropertyLoc = Tok.getLocation(); 971 OMPTraitProperty TIProperty; 972 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen); 973 974 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension) 975 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty, 976 TISelector, Seen)) 977 TIProperty.Kind = TraitProperty::invalid; 978 979 // If we have an invalid property here we already issued a warning. 980 if (TIProperty.Kind == TraitProperty::invalid) { 981 if (PropertyLoc != Tok.getLocation()) 982 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 983 << CONTEXT_TRAIT_LVL; 984 return; 985 } 986 987 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind, 988 TISelector.Kind, Set)) { 989 990 // If we make it here the property, selector, set, score, condition, ... are 991 // all valid (or have been corrected). Thus we can record the property. 992 TISelector.Properties.push_back(TIProperty); 993 return; 994 } 995 996 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector) 997 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 998 TIProperty.RawString) 999 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1000 << getOpenMPContextTraitSetName(Set); 1001 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property) 1002 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 1003 TIProperty.RawString) 1004 << getOpenMPContextTraitSelectorName( 1005 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind)) 1006 << getOpenMPContextTraitSetName( 1007 getOpenMPContextTraitSetForProperty(TIProperty.Kind)); 1008 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1009 << CONTEXT_TRAIT_LVL; 1010 } 1011 1012 void Parser::parseOMPTraitSelectorKind( 1013 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1014 llvm::StringMap<SourceLocation> &Seen) { 1015 TISelector.Kind = TraitSelector::invalid; 1016 1017 SourceLocation NameLoc = Tok.getLocation(); 1018 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL 1019 ); 1020 if (Name.empty()) { 1021 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1022 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1023 return; 1024 } 1025 1026 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name); 1027 if (TISelector.Kind != TraitSelector::invalid) { 1028 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL)) 1029 TISelector.Kind = TraitSelector::invalid; 1030 return; 1031 } 1032 1033 // It follows diagnosis and helping notes. 1034 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector) 1035 << Name << getOpenMPContextTraitSetName(Set); 1036 1037 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 1038 if (SetForName != TraitSet::invalid) { 1039 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1040 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL; 1041 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1042 << Name << "<selector-name>" 1043 << "<property-name>"; 1044 return; 1045 } 1046 for (const auto &PotentialSet : 1047 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1048 TraitSet::device}) { 1049 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1050 PotentialSet, TraitSelector::invalid, Name); 1051 if (PropertyForName == TraitProperty::invalid) 1052 continue; 1053 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1054 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL; 1055 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1056 << getOpenMPContextTraitSetName( 1057 getOpenMPContextTraitSetForProperty(PropertyForName)) 1058 << getOpenMPContextTraitSelectorName( 1059 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1060 << ("(" + Name + ")").str(); 1061 return; 1062 } 1063 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1064 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1065 } 1066 1067 /// Parse optional 'score' '(' <expr> ')' ':'. 1068 static ExprResult parseContextScore(Parser &P) { 1069 ExprResult ScoreExpr; 1070 llvm::SmallString<16> Buffer; 1071 StringRef SelectorName = 1072 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 1073 if (!SelectorName.equals("score")) 1074 return ScoreExpr; 1075 (void)P.ConsumeToken(); 1076 SourceLocation RLoc; 1077 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); 1078 // Parse ':' 1079 if (P.getCurToken().is(tok::colon)) 1080 (void)P.ConsumeAnyToken(); 1081 else 1082 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected) 1083 << "':'" 1084 << "score expression"; 1085 return ScoreExpr; 1086 } 1087 1088 /// Parses an OpenMP context selector. 1089 /// 1090 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')'] 1091 void Parser::parseOMPContextSelector( 1092 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1093 llvm::StringMap<SourceLocation> &SeenSelectors) { 1094 unsigned short OuterPC = ParenCount; 1095 1096 // If anything went wrong we issue an error or warning and then skip the rest 1097 // of the selector. However, commas are ambiguous so we look for the nesting 1098 // of parentheses here as well. 1099 auto FinishSelector = [OuterPC, this]() -> void { 1100 bool Done = false; 1101 while (!Done) { 1102 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma, 1103 tok::annot_pragma_openmp_end}, 1104 StopBeforeMatch)) 1105 ; 1106 if (Tok.is(tok::r_paren) && OuterPC > ParenCount) 1107 (void)ConsumeParen(); 1108 if (OuterPC <= ParenCount) { 1109 Done = true; 1110 break; 1111 } 1112 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) { 1113 Done = true; 1114 break; 1115 } 1116 (void)ConsumeAnyToken(); 1117 } 1118 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1119 << CONTEXT_SELECTOR_LVL; 1120 }; 1121 1122 SourceLocation SelectorLoc = Tok.getLocation(); 1123 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors); 1124 if (TISelector.Kind == TraitSelector::invalid) 1125 return FinishSelector(); 1126 1127 bool AllowsTraitScore = false; 1128 bool RequiresProperty = false; 1129 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore, 1130 RequiresProperty)) { 1131 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set) 1132 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1133 << getOpenMPContextTraitSetName(Set); 1134 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector) 1135 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1136 << getOpenMPContextTraitSetName( 1137 getOpenMPContextTraitSetForSelector(TISelector.Kind)) 1138 << RequiresProperty; 1139 return FinishSelector(); 1140 } 1141 1142 if (!RequiresProperty) { 1143 TISelector.Properties.push_back( 1144 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind), 1145 getOpenMPContextTraitSelectorName(TISelector.Kind)}); 1146 return; 1147 } 1148 1149 if (!Tok.is(tok::l_paren)) { 1150 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties) 1151 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1152 << getOpenMPContextTraitSetName(Set); 1153 return FinishSelector(); 1154 } 1155 1156 if (TISelector.Kind == TraitSelector::user_condition) { 1157 SourceLocation RLoc; 1158 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc); 1159 if (!Condition.isUsable()) 1160 return FinishSelector(); 1161 TISelector.ScoreOrCondition = Condition.get(); 1162 TISelector.Properties.push_back( 1163 {TraitProperty::user_condition_unknown, "<condition>"}); 1164 return; 1165 } 1166 1167 BalancedDelimiterTracker BDT(*this, tok::l_paren, 1168 tok::annot_pragma_openmp_end); 1169 // Parse '('. 1170 (void)BDT.consumeOpen(); 1171 1172 SourceLocation ScoreLoc = Tok.getLocation(); 1173 ExprResult Score = parseContextScore(*this); 1174 1175 if (!AllowsTraitScore && !Score.isUnset()) { 1176 if (Score.isUsable()) { 1177 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1178 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1179 << getOpenMPContextTraitSetName(Set) << Score.get(); 1180 } else { 1181 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1182 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1183 << getOpenMPContextTraitSetName(Set) << "<invalid>"; 1184 } 1185 Score = ExprResult(); 1186 } 1187 1188 if (Score.isUsable()) 1189 TISelector.ScoreOrCondition = Score.get(); 1190 1191 llvm::StringMap<SourceLocation> SeenProperties; 1192 do { 1193 parseOMPContextProperty(TISelector, Set, SeenProperties); 1194 } while (TryConsumeToken(tok::comma)); 1195 1196 // Parse ')'. 1197 BDT.consumeClose(); 1198 } 1199 1200 void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet, 1201 llvm::StringMap<SourceLocation> &Seen) { 1202 TISet.Kind = TraitSet::invalid; 1203 1204 SourceLocation NameLoc = Tok.getLocation(); 1205 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL 1206 ); 1207 if (Name.empty()) { 1208 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1209 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1210 return; 1211 } 1212 1213 TISet.Kind = getOpenMPContextTraitSetKind(Name); 1214 if (TISet.Kind != TraitSet::invalid) { 1215 if (checkForDuplicates(*this, Name, NameLoc, Seen, 1216 CONTEXT_SELECTOR_SET_LVL)) 1217 TISet.Kind = TraitSet::invalid; 1218 return; 1219 } 1220 1221 // It follows diagnosis and helping notes. 1222 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name; 1223 1224 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 1225 if (SelectorForName != TraitSelector::invalid) { 1226 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1227 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL; 1228 bool AllowsTraitScore = false; 1229 bool RequiresProperty = false; 1230 isValidTraitSelectorForTraitSet( 1231 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 1232 AllowsTraitScore, RequiresProperty); 1233 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1234 << getOpenMPContextTraitSetName( 1235 getOpenMPContextTraitSetForSelector(SelectorForName)) 1236 << Name << (RequiresProperty ? "(<property-name>)" : ""); 1237 return; 1238 } 1239 for (const auto &PotentialSet : 1240 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1241 TraitSet::device}) { 1242 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1243 PotentialSet, TraitSelector::invalid, Name); 1244 if (PropertyForName == TraitProperty::invalid) 1245 continue; 1246 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1247 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL; 1248 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1249 << getOpenMPContextTraitSetName( 1250 getOpenMPContextTraitSetForProperty(PropertyForName)) 1251 << getOpenMPContextTraitSelectorName( 1252 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1253 << ("(" + Name + ")").str(); 1254 return; 1255 } 1256 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1257 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1258 } 1259 1260 /// Parses an OpenMP context selector set. 1261 /// 1262 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}' 1263 void Parser::parseOMPContextSelectorSet( 1264 OMPTraitSet &TISet, 1265 llvm::StringMap<SourceLocation> &SeenSets) { 1266 auto OuterBC = BraceCount; 1267 1268 // If anything went wrong we issue an error or warning and then skip the rest 1269 // of the set. However, commas are ambiguous so we look for the nesting 1270 // of braces here as well. 1271 auto FinishSelectorSet = [this, OuterBC]() -> void { 1272 bool Done = false; 1273 while (!Done) { 1274 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren, 1275 tok::annot_pragma_openmp_end}, 1276 StopBeforeMatch)) 1277 ; 1278 if (Tok.is(tok::r_brace) && OuterBC > BraceCount) 1279 (void)ConsumeBrace(); 1280 if (OuterBC <= BraceCount) { 1281 Done = true; 1282 break; 1283 } 1284 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) { 1285 Done = true; 1286 break; 1287 } 1288 (void)ConsumeAnyToken(); 1289 } 1290 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1291 << CONTEXT_SELECTOR_SET_LVL; 1292 }; 1293 1294 parseOMPTraitSetKind(TISet, SeenSets); 1295 if (TISet.Kind == TraitSet::invalid) 1296 return FinishSelectorSet(); 1297 1298 // Parse '='. 1299 if (!TryConsumeToken(tok::equal)) 1300 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1301 << "=" 1302 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) + 1303 "\"") 1304 .str(); 1305 1306 // Parse '{'. 1307 if (Tok.is(tok::l_brace)) { 1308 (void)ConsumeBrace(); 1309 } else { 1310 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1311 << "{" 1312 << ("'=' that follows the context set name \"" + 1313 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1314 .str(); 1315 } 1316 1317 llvm::StringMap<SourceLocation> SeenSelectors; 1318 do { 1319 OMPTraitSelector TISelector; 1320 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors); 1321 if (TISelector.Kind != TraitSelector::invalid && 1322 !TISelector.Properties.empty()) 1323 TISet.Selectors.push_back(TISelector); 1324 } while (TryConsumeToken(tok::comma)); 1325 1326 // Parse '}'. 1327 if (Tok.is(tok::r_brace)) { 1328 (void)ConsumeBrace(); 1329 } else { 1330 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1331 << "}" 1332 << ("context selectors for the context set \"" + 1333 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1334 .str(); 1335 } 1336 } 1337 1338 /// Parse OpenMP context selectors: 1339 /// 1340 /// <trait-set-selector> [, <trait-set-selector>]* 1341 bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo& TI) { 1342 llvm::StringMap<SourceLocation> SeenSets; 1343 do { 1344 OMPTraitSet TISet; 1345 parseOMPContextSelectorSet(TISet, SeenSets); 1346 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty()) 1347 TI.Sets.push_back(TISet); 1348 } while (TryConsumeToken(tok::comma)); 1349 1350 return false; 1351 } 1352 1353 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. 1354 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, 1355 CachedTokens &Toks, 1356 SourceLocation Loc) { 1357 PP.EnterToken(Tok, /*IsReinject*/ true); 1358 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1359 /*IsReinject*/ true); 1360 // Consume the previously pushed token. 1361 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1362 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1363 1364 FNContextRAII FnContext(*this, Ptr); 1365 // Parse function declaration id. 1366 SourceLocation RLoc; 1367 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs 1368 // instead of MemberExprs. 1369 ExprResult AssociatedFunction; 1370 { 1371 // Do not mark function as is used to prevent its emission if this is the 1372 // only place where it is used. 1373 EnterExpressionEvaluationContext Unevaluated( 1374 Actions, Sema::ExpressionEvaluationContext::Unevaluated); 1375 AssociatedFunction = ParseOpenMPParensExpr( 1376 getOpenMPDirectiveName(OMPD_declare_variant), RLoc, 1377 /*IsAddressOfOperand=*/true); 1378 } 1379 if (!AssociatedFunction.isUsable()) { 1380 if (!Tok.is(tok::annot_pragma_openmp_end)) 1381 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1382 ; 1383 // Skip the last annot_pragma_openmp_end. 1384 (void)ConsumeAnnotationToken(); 1385 return; 1386 } 1387 1388 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 1389 if (parseOMPDeclareVariantMatchClause(Loc, TI)) 1390 return; 1391 1392 Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = 1393 Actions.checkOpenMPDeclareVariantFunction( 1394 Ptr, AssociatedFunction.get(), TI, 1395 SourceRange(Loc, Tok.getLocation())); 1396 1397 // Skip last tokens. 1398 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1399 ConsumeAnyToken(); 1400 if (DeclVarData && !TI.Sets.empty()) 1401 Actions.ActOnOpenMPDeclareVariantDirective( 1402 DeclVarData->first, DeclVarData->second, TI, 1403 SourceRange(Loc, Tok.getLocation())); 1404 1405 // Skip the last annot_pragma_openmp_end. 1406 (void)ConsumeAnnotationToken(); 1407 } 1408 1409 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, 1410 OMPTraitInfo &TI) { 1411 // Parse 'match'. 1412 OpenMPClauseKind CKind = Tok.isAnnotation() 1413 ? OMPC_unknown 1414 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1415 if (CKind != OMPC_match) { 1416 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1417 << getOpenMPClauseName(OMPC_match); 1418 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 1419 ; 1420 // Skip the last annot_pragma_openmp_end. 1421 (void)ConsumeAnnotationToken(); 1422 return true; 1423 } 1424 (void)ConsumeToken(); 1425 // Parse '('. 1426 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1427 if (T.expectAndConsume(diag::err_expected_lparen_after, 1428 getOpenMPClauseName(OMPC_match).data())) { 1429 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1430 ; 1431 // Skip the last annot_pragma_openmp_end. 1432 (void)ConsumeAnnotationToken(); 1433 return true; 1434 } 1435 1436 // Parse inner context selectors. 1437 parseOMPContextSelectors(Loc, TI); 1438 1439 // Parse ')' 1440 (void)T.consumeClose(); 1441 return false; 1442 } 1443 1444 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1445 /// 1446 /// default-clause: 1447 /// 'default' '(' 'none' | 'shared' | 'firstprivate' ') 1448 /// 1449 /// proc_bind-clause: 1450 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1451 /// 1452 /// device_type-clause: 1453 /// 'device_type' '(' 'host' | 'nohost' | 'any' )' 1454 namespace { 1455 struct SimpleClauseData { 1456 unsigned Type; 1457 SourceLocation Loc; 1458 SourceLocation LOpen; 1459 SourceLocation TypeLoc; 1460 SourceLocation RLoc; 1461 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, 1462 SourceLocation TypeLoc, SourceLocation RLoc) 1463 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} 1464 }; 1465 } // anonymous namespace 1466 1467 static Optional<SimpleClauseData> 1468 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { 1469 const Token &Tok = P.getCurToken(); 1470 SourceLocation Loc = Tok.getLocation(); 1471 SourceLocation LOpen = P.ConsumeToken(); 1472 // Parse '('. 1473 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 1474 if (T.expectAndConsume(diag::err_expected_lparen_after, 1475 getOpenMPClauseName(Kind).data())) 1476 return llvm::None; 1477 1478 unsigned Type = getOpenMPSimpleClauseType( 1479 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok), 1480 P.getLangOpts().OpenMP); 1481 SourceLocation TypeLoc = Tok.getLocation(); 1482 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1483 Tok.isNot(tok::annot_pragma_openmp_end)) 1484 P.ConsumeAnyToken(); 1485 1486 // Parse ')'. 1487 SourceLocation RLoc = Tok.getLocation(); 1488 if (!T.consumeClose()) 1489 RLoc = T.getCloseLocation(); 1490 1491 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); 1492 } 1493 1494 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { 1495 // OpenMP 4.5 syntax with list of entities. 1496 Sema::NamedDeclSetType SameDirectiveDecls; 1497 SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation, 1498 NamedDecl *>, 1499 4> 1500 DeclareTargetDecls; 1501 OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; 1502 SourceLocation DeviceTypeLoc; 1503 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1504 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 1505 if (Tok.is(tok::identifier)) { 1506 IdentifierInfo *II = Tok.getIdentifierInfo(); 1507 StringRef ClauseName = II->getName(); 1508 bool IsDeviceTypeClause = 1509 getLangOpts().OpenMP >= 50 && 1510 getOpenMPClauseKind(ClauseName) == OMPC_device_type; 1511 // Parse 'to|link|device_type' clauses. 1512 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) && 1513 !IsDeviceTypeClause) { 1514 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1515 << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0); 1516 break; 1517 } 1518 // Parse 'device_type' clause and go to next clause if any. 1519 if (IsDeviceTypeClause) { 1520 Optional<SimpleClauseData> DevTypeData = 1521 parseOpenMPSimpleClause(*this, OMPC_device_type); 1522 if (DevTypeData.hasValue()) { 1523 if (DeviceTypeLoc.isValid()) { 1524 // We already saw another device_type clause, diagnose it. 1525 Diag(DevTypeData.getValue().Loc, 1526 diag::warn_omp_more_one_device_type_clause); 1527 } 1528 switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { 1529 case OMPC_DEVICE_TYPE_any: 1530 DT = OMPDeclareTargetDeclAttr::DT_Any; 1531 break; 1532 case OMPC_DEVICE_TYPE_host: 1533 DT = OMPDeclareTargetDeclAttr::DT_Host; 1534 break; 1535 case OMPC_DEVICE_TYPE_nohost: 1536 DT = OMPDeclareTargetDeclAttr::DT_NoHost; 1537 break; 1538 case OMPC_DEVICE_TYPE_unknown: 1539 llvm_unreachable("Unexpected device_type"); 1540 } 1541 DeviceTypeLoc = DevTypeData.getValue().Loc; 1542 } 1543 continue; 1544 } 1545 ConsumeToken(); 1546 } 1547 auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls]( 1548 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 1549 NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName( 1550 getCurScope(), SS, NameInfo, SameDirectiveDecls); 1551 if (ND) 1552 DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND); 1553 }; 1554 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 1555 /*AllowScopeSpecifier=*/true)) 1556 break; 1557 1558 // Consume optional ','. 1559 if (Tok.is(tok::comma)) 1560 ConsumeToken(); 1561 } 1562 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1563 ConsumeAnyToken(); 1564 for (auto &MTLocDecl : DeclareTargetDecls) { 1565 OMPDeclareTargetDeclAttr::MapTypeTy MT; 1566 SourceLocation Loc; 1567 NamedDecl *ND; 1568 std::tie(MT, Loc, ND) = MTLocDecl; 1569 // device_type clause is applied only to functions. 1570 Actions.ActOnOpenMPDeclareTargetName( 1571 ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT); 1572 } 1573 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), 1574 SameDirectiveDecls.end()); 1575 if (Decls.empty()) 1576 return DeclGroupPtrTy(); 1577 return Actions.BuildDeclaratorGroup(Decls); 1578 } 1579 1580 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) { 1581 // The last seen token is annot_pragma_openmp_end - need to check for 1582 // extra tokens. 1583 if (Tok.is(tok::annot_pragma_openmp_end)) 1584 return; 1585 1586 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1587 << getOpenMPDirectiveName(DKind); 1588 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1589 ConsumeAnyToken(); 1590 } 1591 1592 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind, 1593 OpenMPDirectiveKind ExpectedKind, 1594 OpenMPDirectiveKind FoundKind, 1595 SourceLocation BeginLoc, 1596 SourceLocation FoundLoc, 1597 bool SkipUntilOpenMPEnd) { 1598 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1; 1599 1600 if (FoundKind == ExpectedKind) { 1601 ConsumeAnyToken(); 1602 skipUntilPragmaOpenMPEnd(ExpectedKind); 1603 return; 1604 } 1605 1606 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant) 1607 << DiagSelection; 1608 Diag(BeginLoc, diag::note_matching) 1609 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str(); 1610 if (SkipUntilOpenMPEnd) 1611 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1612 } 1613 1614 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, 1615 SourceLocation DKLoc) { 1616 parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind, 1617 DKLoc, Tok.getLocation(), 1618 /* SkipUntilOpenMPEnd */ false); 1619 // Skip the last annot_pragma_openmp_end. 1620 if (Tok.is(tok::annot_pragma_openmp_end)) 1621 ConsumeAnnotationToken(); 1622 } 1623 1624 /// Parsing of declarative OpenMP directives. 1625 /// 1626 /// threadprivate-directive: 1627 /// annot_pragma_openmp 'threadprivate' simple-variable-list 1628 /// annot_pragma_openmp_end 1629 /// 1630 /// allocate-directive: 1631 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 1632 /// annot_pragma_openmp_end 1633 /// 1634 /// declare-reduction-directive: 1635 /// annot_pragma_openmp 'declare' 'reduction' [...] 1636 /// annot_pragma_openmp_end 1637 /// 1638 /// declare-mapper-directive: 1639 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 1640 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 1641 /// annot_pragma_openmp_end 1642 /// 1643 /// declare-simd-directive: 1644 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 1645 /// annot_pragma_openmp_end 1646 /// <function declaration/definition> 1647 /// 1648 /// requires directive: 1649 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 1650 /// annot_pragma_openmp_end 1651 /// 1652 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 1653 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, 1654 DeclSpec::TST TagType, Decl *Tag) { 1655 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 1656 ParsingOpenMPDirectiveRAII DirScope(*this); 1657 ParenBraceBracketBalancer BalancerRAIIObj(*this); 1658 1659 SourceLocation Loc; 1660 OpenMPDirectiveKind DKind; 1661 if (Delayed) { 1662 TentativeParsingAction TPA(*this); 1663 Loc = ConsumeAnnotationToken(); 1664 DKind = parseOpenMPDirectiveKind(*this); 1665 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { 1666 // Need to delay parsing until completion of the parent class. 1667 TPA.Revert(); 1668 CachedTokens Toks; 1669 unsigned Cnt = 1; 1670 Toks.push_back(Tok); 1671 while (Cnt && Tok.isNot(tok::eof)) { 1672 (void)ConsumeAnyToken(); 1673 if (Tok.is(tok::annot_pragma_openmp)) 1674 ++Cnt; 1675 else if (Tok.is(tok::annot_pragma_openmp_end)) 1676 --Cnt; 1677 Toks.push_back(Tok); 1678 } 1679 // Skip last annot_pragma_openmp_end. 1680 if (Cnt == 0) 1681 (void)ConsumeAnyToken(); 1682 auto *LP = new LateParsedPragma(this, AS); 1683 LP->takeToks(Toks); 1684 getCurrentClass().LateParsedDeclarations.push_back(LP); 1685 return nullptr; 1686 } 1687 TPA.Commit(); 1688 } else { 1689 Loc = ConsumeAnnotationToken(); 1690 DKind = parseOpenMPDirectiveKind(*this); 1691 } 1692 1693 switch (DKind) { 1694 case OMPD_threadprivate: { 1695 ConsumeToken(); 1696 DeclDirectiveListParserHelper Helper(this, DKind); 1697 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1698 /*AllowScopeSpecifier=*/true)) { 1699 skipUntilPragmaOpenMPEnd(DKind); 1700 // Skip the last annot_pragma_openmp_end. 1701 ConsumeAnnotationToken(); 1702 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 1703 Helper.getIdentifiers()); 1704 } 1705 break; 1706 } 1707 case OMPD_allocate: { 1708 ConsumeToken(); 1709 DeclDirectiveListParserHelper Helper(this, DKind); 1710 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1711 /*AllowScopeSpecifier=*/true)) { 1712 SmallVector<OMPClause *, 1> Clauses; 1713 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1714 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1715 llvm::omp::Clause_enumSize + 1> 1716 FirstClauses(llvm::omp::Clause_enumSize + 1); 1717 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1718 OpenMPClauseKind CKind = 1719 Tok.isAnnotation() ? OMPC_unknown 1720 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1721 Actions.StartOpenMPClause(CKind); 1722 OMPClause *Clause = ParseOpenMPClause( 1723 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 1724 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1725 StopBeforeMatch); 1726 FirstClauses[unsigned(CKind)].setInt(true); 1727 if (Clause != nullptr) 1728 Clauses.push_back(Clause); 1729 if (Tok.is(tok::annot_pragma_openmp_end)) { 1730 Actions.EndOpenMPClause(); 1731 break; 1732 } 1733 // Skip ',' if any. 1734 if (Tok.is(tok::comma)) 1735 ConsumeToken(); 1736 Actions.EndOpenMPClause(); 1737 } 1738 skipUntilPragmaOpenMPEnd(DKind); 1739 } 1740 // Skip the last annot_pragma_openmp_end. 1741 ConsumeAnnotationToken(); 1742 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 1743 Clauses); 1744 } 1745 break; 1746 } 1747 case OMPD_requires: { 1748 SourceLocation StartLoc = ConsumeToken(); 1749 SmallVector<OMPClause *, 5> Clauses; 1750 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1751 llvm::omp::Clause_enumSize + 1> 1752 FirstClauses(llvm::omp::Clause_enumSize + 1); 1753 if (Tok.is(tok::annot_pragma_openmp_end)) { 1754 Diag(Tok, diag::err_omp_expected_clause) 1755 << getOpenMPDirectiveName(OMPD_requires); 1756 break; 1757 } 1758 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1759 OpenMPClauseKind CKind = Tok.isAnnotation() 1760 ? OMPC_unknown 1761 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1762 Actions.StartOpenMPClause(CKind); 1763 OMPClause *Clause = ParseOpenMPClause( 1764 OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt()); 1765 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1766 StopBeforeMatch); 1767 FirstClauses[unsigned(CKind)].setInt(true); 1768 if (Clause != nullptr) 1769 Clauses.push_back(Clause); 1770 if (Tok.is(tok::annot_pragma_openmp_end)) { 1771 Actions.EndOpenMPClause(); 1772 break; 1773 } 1774 // Skip ',' if any. 1775 if (Tok.is(tok::comma)) 1776 ConsumeToken(); 1777 Actions.EndOpenMPClause(); 1778 } 1779 // Consume final annot_pragma_openmp_end 1780 if (Clauses.empty()) { 1781 Diag(Tok, diag::err_omp_expected_clause) 1782 << getOpenMPDirectiveName(OMPD_requires); 1783 ConsumeAnnotationToken(); 1784 return nullptr; 1785 } 1786 ConsumeAnnotationToken(); 1787 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 1788 } 1789 case OMPD_declare_reduction: 1790 ConsumeToken(); 1791 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 1792 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 1793 // Skip the last annot_pragma_openmp_end. 1794 ConsumeAnnotationToken(); 1795 return Res; 1796 } 1797 break; 1798 case OMPD_declare_mapper: { 1799 ConsumeToken(); 1800 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 1801 // Skip the last annot_pragma_openmp_end. 1802 ConsumeAnnotationToken(); 1803 return Res; 1804 } 1805 break; 1806 } 1807 case OMPD_begin_declare_variant: { 1808 // The syntax is: 1809 // { #pragma omp begin declare variant clause } 1810 // <function-declaration-or-definition-sequence> 1811 // { #pragma omp end declare variant } 1812 // 1813 ConsumeToken(); 1814 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 1815 if (parseOMPDeclareVariantMatchClause(Loc, TI)) 1816 break; 1817 1818 // Skip last tokens. 1819 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant); 1820 1821 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 1822 1823 VariantMatchInfo VMI; 1824 ASTContext &ASTCtx = Actions.getASTContext(); 1825 TI.getAsVariantMatchInfo(ASTCtx, VMI); 1826 1827 std::function<void(StringRef)> DiagUnknownTrait = [this, Loc]( 1828 StringRef ISATrait) { 1829 // TODO Track the selector locations in a way that is accessible here to 1830 // improve the diagnostic location. 1831 Diag(Loc, diag::warn_unknown_begin_declare_variant_isa_trait) << ISATrait; 1832 }; 1833 TargetOMPContext OMPCtx(ASTCtx, std::move(DiagUnknownTrait), 1834 /* CurrentFunctionDecl */ nullptr); 1835 1836 if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) { 1837 Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI); 1838 break; 1839 } 1840 1841 // Elide all the code till the matching end declare variant was found. 1842 unsigned Nesting = 1; 1843 SourceLocation DKLoc; 1844 OpenMPDirectiveKind DK = OMPD_unknown; 1845 do { 1846 DKLoc = Tok.getLocation(); 1847 DK = parseOpenMPDirectiveKind(*this); 1848 if (DK == OMPD_end_declare_variant) 1849 --Nesting; 1850 else if (DK == OMPD_begin_declare_variant) 1851 ++Nesting; 1852 if (!Nesting || isEofOrEom()) 1853 break; 1854 ConsumeAnyToken(); 1855 } while (true); 1856 1857 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, 1858 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true); 1859 if (isEofOrEom()) 1860 return nullptr; 1861 break; 1862 } 1863 case OMPD_end_declare_variant: { 1864 if (Actions.isInOpenMPDeclareVariantScope()) 1865 Actions.ActOnOpenMPEndDeclareVariant(); 1866 else 1867 Diag(Loc, diag::err_expected_begin_declare_variant); 1868 ConsumeToken(); 1869 break; 1870 } 1871 case OMPD_declare_variant: 1872 case OMPD_declare_simd: { 1873 // The syntax is: 1874 // { #pragma omp declare {simd|variant} } 1875 // <function-declaration-or-definition> 1876 // 1877 CachedTokens Toks; 1878 Toks.push_back(Tok); 1879 ConsumeToken(); 1880 while(Tok.isNot(tok::annot_pragma_openmp_end)) { 1881 Toks.push_back(Tok); 1882 ConsumeAnyToken(); 1883 } 1884 Toks.push_back(Tok); 1885 ConsumeAnyToken(); 1886 1887 DeclGroupPtrTy Ptr; 1888 if (Tok.is(tok::annot_pragma_openmp)) { 1889 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, 1890 TagType, Tag); 1891 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 1892 // Here we expect to see some function declaration. 1893 if (AS == AS_none) { 1894 assert(TagType == DeclSpec::TST_unspecified); 1895 MaybeParseCXX11Attributes(Attrs); 1896 ParsingDeclSpec PDS(*this); 1897 Ptr = ParseExternalDeclaration(Attrs, &PDS); 1898 } else { 1899 Ptr = 1900 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1901 } 1902 } 1903 if (!Ptr) { 1904 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) 1905 << (DKind == OMPD_declare_simd ? 0 : 1); 1906 return DeclGroupPtrTy(); 1907 } 1908 if (DKind == OMPD_declare_simd) 1909 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 1910 assert(DKind == OMPD_declare_variant && 1911 "Expected declare variant directive only"); 1912 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); 1913 return Ptr; 1914 } 1915 case OMPD_declare_target: { 1916 SourceLocation DTLoc = ConsumeAnyToken(); 1917 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1918 return ParseOMPDeclareTargetClauses(); 1919 } 1920 1921 // Skip the last annot_pragma_openmp_end. 1922 ConsumeAnyToken(); 1923 1924 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 1925 return DeclGroupPtrTy(); 1926 1927 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 1928 llvm::SmallVector<Decl *, 4> Decls; 1929 DKind = parseOpenMPDirectiveKind(*this); 1930 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && 1931 Tok.isNot(tok::r_brace)) { 1932 DeclGroupPtrTy Ptr; 1933 // Here we expect to see some function declaration. 1934 if (AS == AS_none) { 1935 assert(TagType == DeclSpec::TST_unspecified); 1936 MaybeParseCXX11Attributes(Attrs); 1937 ParsingDeclSpec PDS(*this); 1938 Ptr = ParseExternalDeclaration(Attrs, &PDS); 1939 } else { 1940 Ptr = 1941 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1942 } 1943 if (Ptr) { 1944 DeclGroupRef Ref = Ptr.get(); 1945 Decls.append(Ref.begin(), Ref.end()); 1946 } 1947 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 1948 TentativeParsingAction TPA(*this); 1949 ConsumeAnnotationToken(); 1950 DKind = parseOpenMPDirectiveKind(*this); 1951 if (DKind != OMPD_end_declare_target) 1952 TPA.Revert(); 1953 else 1954 TPA.Commit(); 1955 } 1956 } 1957 1958 ParseOMPEndDeclareTargetDirective(DKind, DTLoc); 1959 Actions.ActOnFinishOpenMPDeclareTargetDirective(); 1960 return Actions.BuildDeclaratorGroup(Decls); 1961 } 1962 case OMPD_unknown: 1963 Diag(Tok, diag::err_omp_unknown_directive); 1964 break; 1965 case OMPD_parallel: 1966 case OMPD_simd: 1967 case OMPD_task: 1968 case OMPD_taskyield: 1969 case OMPD_barrier: 1970 case OMPD_taskwait: 1971 case OMPD_taskgroup: 1972 case OMPD_flush: 1973 case OMPD_depobj: 1974 case OMPD_scan: 1975 case OMPD_for: 1976 case OMPD_for_simd: 1977 case OMPD_sections: 1978 case OMPD_section: 1979 case OMPD_single: 1980 case OMPD_master: 1981 case OMPD_ordered: 1982 case OMPD_critical: 1983 case OMPD_parallel_for: 1984 case OMPD_parallel_for_simd: 1985 case OMPD_parallel_sections: 1986 case OMPD_parallel_master: 1987 case OMPD_atomic: 1988 case OMPD_target: 1989 case OMPD_teams: 1990 case OMPD_cancellation_point: 1991 case OMPD_cancel: 1992 case OMPD_target_data: 1993 case OMPD_target_enter_data: 1994 case OMPD_target_exit_data: 1995 case OMPD_target_parallel: 1996 case OMPD_target_parallel_for: 1997 case OMPD_taskloop: 1998 case OMPD_taskloop_simd: 1999 case OMPD_master_taskloop: 2000 case OMPD_master_taskloop_simd: 2001 case OMPD_parallel_master_taskloop: 2002 case OMPD_parallel_master_taskloop_simd: 2003 case OMPD_distribute: 2004 case OMPD_end_declare_target: 2005 case OMPD_target_update: 2006 case OMPD_distribute_parallel_for: 2007 case OMPD_distribute_parallel_for_simd: 2008 case OMPD_distribute_simd: 2009 case OMPD_target_parallel_for_simd: 2010 case OMPD_target_simd: 2011 case OMPD_teams_distribute: 2012 case OMPD_teams_distribute_simd: 2013 case OMPD_teams_distribute_parallel_for_simd: 2014 case OMPD_teams_distribute_parallel_for: 2015 case OMPD_target_teams: 2016 case OMPD_target_teams_distribute: 2017 case OMPD_target_teams_distribute_parallel_for: 2018 case OMPD_target_teams_distribute_parallel_for_simd: 2019 case OMPD_target_teams_distribute_simd: 2020 Diag(Tok, diag::err_omp_unexpected_directive) 2021 << 1 << getOpenMPDirectiveName(DKind); 2022 break; 2023 default: 2024 break; 2025 } 2026 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2027 ConsumeAnyToken(); 2028 ConsumeAnyToken(); 2029 return nullptr; 2030 } 2031 2032 /// Parsing of declarative or executable OpenMP directives. 2033 /// 2034 /// threadprivate-directive: 2035 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2036 /// annot_pragma_openmp_end 2037 /// 2038 /// allocate-directive: 2039 /// annot_pragma_openmp 'allocate' simple-variable-list 2040 /// annot_pragma_openmp_end 2041 /// 2042 /// declare-reduction-directive: 2043 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 2044 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 2045 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 2046 /// annot_pragma_openmp_end 2047 /// 2048 /// declare-mapper-directive: 2049 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2050 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2051 /// annot_pragma_openmp_end 2052 /// 2053 /// executable-directive: 2054 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 2055 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 2056 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | 2057 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 2058 /// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target 2059 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 2060 /// 'master taskloop' | 'master taskloop simd' | 'parallel master 2061 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target 2062 /// enter data' | 'target exit data' | 'target parallel' | 'target 2063 /// parallel for' | 'target update' | 'distribute parallel for' | 2064 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel 2065 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute 2066 /// simd' | 'teams distribute parallel for simd' | 'teams distribute 2067 /// parallel for' | 'target teams' | 'target teams distribute' | 'target 2068 /// teams distribute parallel for' | 'target teams distribute parallel 2069 /// for simd' | 'target teams distribute simd' {clause} 2070 /// annot_pragma_openmp_end 2071 /// 2072 StmtResult 2073 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 2074 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 2075 ParsingOpenMPDirectiveRAII DirScope(*this); 2076 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2077 SmallVector<OMPClause *, 5> Clauses; 2078 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2079 llvm::omp::Clause_enumSize + 1> 2080 FirstClauses(llvm::omp::Clause_enumSize + 1); 2081 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 2082 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 2083 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; 2084 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 2085 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 2086 // Name of critical directive. 2087 DeclarationNameInfo DirName; 2088 StmtResult Directive = StmtError(); 2089 bool HasAssociatedStatement = true; 2090 2091 switch (DKind) { 2092 case OMPD_threadprivate: { 2093 // FIXME: Should this be permitted in C++? 2094 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2095 ParsedStmtContext()) { 2096 Diag(Tok, diag::err_omp_immediate_directive) 2097 << getOpenMPDirectiveName(DKind) << 0; 2098 } 2099 ConsumeToken(); 2100 DeclDirectiveListParserHelper Helper(this, DKind); 2101 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2102 /*AllowScopeSpecifier=*/false)) { 2103 skipUntilPragmaOpenMPEnd(DKind); 2104 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 2105 Loc, Helper.getIdentifiers()); 2106 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2107 } 2108 SkipUntil(tok::annot_pragma_openmp_end); 2109 break; 2110 } 2111 case OMPD_allocate: { 2112 // FIXME: Should this be permitted in C++? 2113 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2114 ParsedStmtContext()) { 2115 Diag(Tok, diag::err_omp_immediate_directive) 2116 << getOpenMPDirectiveName(DKind) << 0; 2117 } 2118 ConsumeToken(); 2119 DeclDirectiveListParserHelper Helper(this, DKind); 2120 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2121 /*AllowScopeSpecifier=*/false)) { 2122 SmallVector<OMPClause *, 1> Clauses; 2123 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2124 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2125 llvm::omp::Clause_enumSize + 1> 2126 FirstClauses(llvm::omp::Clause_enumSize + 1); 2127 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2128 OpenMPClauseKind CKind = 2129 Tok.isAnnotation() ? OMPC_unknown 2130 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2131 Actions.StartOpenMPClause(CKind); 2132 OMPClause *Clause = ParseOpenMPClause( 2133 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2134 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2135 StopBeforeMatch); 2136 FirstClauses[unsigned(CKind)].setInt(true); 2137 if (Clause != nullptr) 2138 Clauses.push_back(Clause); 2139 if (Tok.is(tok::annot_pragma_openmp_end)) { 2140 Actions.EndOpenMPClause(); 2141 break; 2142 } 2143 // Skip ',' if any. 2144 if (Tok.is(tok::comma)) 2145 ConsumeToken(); 2146 Actions.EndOpenMPClause(); 2147 } 2148 skipUntilPragmaOpenMPEnd(DKind); 2149 } 2150 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 2151 Loc, Helper.getIdentifiers(), Clauses); 2152 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2153 } 2154 SkipUntil(tok::annot_pragma_openmp_end); 2155 break; 2156 } 2157 case OMPD_declare_reduction: 2158 ConsumeToken(); 2159 if (DeclGroupPtrTy Res = 2160 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 2161 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2162 ConsumeAnyToken(); 2163 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2164 } else { 2165 SkipUntil(tok::annot_pragma_openmp_end); 2166 } 2167 break; 2168 case OMPD_declare_mapper: { 2169 ConsumeToken(); 2170 if (DeclGroupPtrTy Res = 2171 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 2172 // Skip the last annot_pragma_openmp_end. 2173 ConsumeAnnotationToken(); 2174 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2175 } else { 2176 SkipUntil(tok::annot_pragma_openmp_end); 2177 } 2178 break; 2179 } 2180 case OMPD_flush: 2181 case OMPD_depobj: 2182 case OMPD_scan: 2183 case OMPD_taskyield: 2184 case OMPD_barrier: 2185 case OMPD_taskwait: 2186 case OMPD_cancellation_point: 2187 case OMPD_cancel: 2188 case OMPD_target_enter_data: 2189 case OMPD_target_exit_data: 2190 case OMPD_target_update: 2191 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2192 ParsedStmtContext()) { 2193 Diag(Tok, diag::err_omp_immediate_directive) 2194 << getOpenMPDirectiveName(DKind) << 0; 2195 } 2196 HasAssociatedStatement = false; 2197 // Fall through for further analysis. 2198 LLVM_FALLTHROUGH; 2199 case OMPD_parallel: 2200 case OMPD_simd: 2201 case OMPD_for: 2202 case OMPD_for_simd: 2203 case OMPD_sections: 2204 case OMPD_single: 2205 case OMPD_section: 2206 case OMPD_master: 2207 case OMPD_critical: 2208 case OMPD_parallel_for: 2209 case OMPD_parallel_for_simd: 2210 case OMPD_parallel_sections: 2211 case OMPD_parallel_master: 2212 case OMPD_task: 2213 case OMPD_ordered: 2214 case OMPD_atomic: 2215 case OMPD_target: 2216 case OMPD_teams: 2217 case OMPD_taskgroup: 2218 case OMPD_target_data: 2219 case OMPD_target_parallel: 2220 case OMPD_target_parallel_for: 2221 case OMPD_taskloop: 2222 case OMPD_taskloop_simd: 2223 case OMPD_master_taskloop: 2224 case OMPD_master_taskloop_simd: 2225 case OMPD_parallel_master_taskloop: 2226 case OMPD_parallel_master_taskloop_simd: 2227 case OMPD_distribute: 2228 case OMPD_distribute_parallel_for: 2229 case OMPD_distribute_parallel_for_simd: 2230 case OMPD_distribute_simd: 2231 case OMPD_target_parallel_for_simd: 2232 case OMPD_target_simd: 2233 case OMPD_teams_distribute: 2234 case OMPD_teams_distribute_simd: 2235 case OMPD_teams_distribute_parallel_for_simd: 2236 case OMPD_teams_distribute_parallel_for: 2237 case OMPD_target_teams: 2238 case OMPD_target_teams_distribute: 2239 case OMPD_target_teams_distribute_parallel_for: 2240 case OMPD_target_teams_distribute_parallel_for_simd: 2241 case OMPD_target_teams_distribute_simd: { 2242 // Special processing for flush and depobj clauses. 2243 Token ImplicitTok; 2244 bool ImplicitClauseAllowed = false; 2245 if (DKind == OMPD_flush || DKind == OMPD_depobj) { 2246 ImplicitTok = Tok; 2247 ImplicitClauseAllowed = true; 2248 } 2249 ConsumeToken(); 2250 // Parse directive name of the 'critical' directive if any. 2251 if (DKind == OMPD_critical) { 2252 BalancedDelimiterTracker T(*this, tok::l_paren, 2253 tok::annot_pragma_openmp_end); 2254 if (!T.consumeOpen()) { 2255 if (Tok.isAnyIdentifier()) { 2256 DirName = 2257 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 2258 ConsumeAnyToken(); 2259 } else { 2260 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 2261 } 2262 T.consumeClose(); 2263 } 2264 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 2265 CancelRegion = parseOpenMPDirectiveKind(*this); 2266 if (Tok.isNot(tok::annot_pragma_openmp_end)) 2267 ConsumeToken(); 2268 } 2269 2270 if (isOpenMPLoopDirective(DKind)) 2271 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 2272 if (isOpenMPSimdDirective(DKind)) 2273 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 2274 ParseScope OMPDirectiveScope(this, ScopeFlags); 2275 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 2276 2277 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2278 bool HasImplicitClause = false; 2279 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { 2280 HasImplicitClause = true; 2281 // Push copy of the current token back to stream to properly parse 2282 // pseudo-clause OMPFlushClause or OMPDepobjClause. 2283 PP.EnterToken(Tok, /*IsReinject*/ true); 2284 PP.EnterToken(ImplicitTok, /*IsReinject*/ true); 2285 ConsumeAnyToken(); 2286 } 2287 OpenMPClauseKind CKind = Tok.isAnnotation() 2288 ? OMPC_unknown 2289 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2290 if (HasImplicitClause) { 2291 assert(CKind == OMPC_unknown && "Must be unknown implicit clause."); 2292 if (DKind == OMPD_flush) { 2293 CKind = OMPC_flush; 2294 } else { 2295 assert(DKind == OMPD_depobj && 2296 "Expected flush or depobj directives."); 2297 CKind = OMPC_depobj; 2298 } 2299 } 2300 // No more implicit clauses allowed. 2301 ImplicitClauseAllowed = false; 2302 Actions.StartOpenMPClause(CKind); 2303 HasImplicitClause = false; 2304 OMPClause *Clause = ParseOpenMPClause( 2305 DKind, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2306 FirstClauses[unsigned(CKind)].setInt(true); 2307 if (Clause) { 2308 FirstClauses[unsigned(CKind)].setPointer(Clause); 2309 Clauses.push_back(Clause); 2310 } 2311 2312 // Skip ',' if any. 2313 if (Tok.is(tok::comma)) 2314 ConsumeToken(); 2315 Actions.EndOpenMPClause(); 2316 } 2317 // End location of the directive. 2318 EndLoc = Tok.getLocation(); 2319 // Consume final annot_pragma_openmp_end. 2320 ConsumeAnnotationToken(); 2321 2322 // OpenMP [2.13.8, ordered Construct, Syntax] 2323 // If the depend clause is specified, the ordered construct is a stand-alone 2324 // directive. 2325 if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) { 2326 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2327 ParsedStmtContext()) { 2328 Diag(Loc, diag::err_omp_immediate_directive) 2329 << getOpenMPDirectiveName(DKind) << 1 2330 << getOpenMPClauseName(OMPC_depend); 2331 } 2332 HasAssociatedStatement = false; 2333 } 2334 2335 StmtResult AssociatedStmt; 2336 if (HasAssociatedStatement) { 2337 // The body is a block scope like in Lambdas and Blocks. 2338 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2339 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 2340 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 2341 // should have at least one compound statement scope within it. 2342 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2343 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 2344 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2345 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 2346 DKind == OMPD_target_exit_data) { 2347 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2348 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 2349 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 2350 /*isStmtExpr=*/false)); 2351 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2352 } 2353 Directive = Actions.ActOnOpenMPExecutableDirective( 2354 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 2355 EndLoc); 2356 2357 // Exit scope. 2358 Actions.EndOpenMPDSABlock(Directive.get()); 2359 OMPDirectiveScope.Exit(); 2360 break; 2361 } 2362 case OMPD_declare_simd: 2363 case OMPD_declare_target: 2364 case OMPD_end_declare_target: 2365 case OMPD_requires: 2366 case OMPD_begin_declare_variant: 2367 case OMPD_end_declare_variant: 2368 case OMPD_declare_variant: 2369 Diag(Tok, diag::err_omp_unexpected_directive) 2370 << 1 << getOpenMPDirectiveName(DKind); 2371 SkipUntil(tok::annot_pragma_openmp_end); 2372 break; 2373 case OMPD_unknown: 2374 default: 2375 Diag(Tok, diag::err_omp_unknown_directive); 2376 SkipUntil(tok::annot_pragma_openmp_end); 2377 break; 2378 } 2379 return Directive; 2380 } 2381 2382 // Parses simple list: 2383 // simple-variable-list: 2384 // '(' id-expression {, id-expression} ')' 2385 // 2386 bool Parser::ParseOpenMPSimpleVarList( 2387 OpenMPDirectiveKind Kind, 2388 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 2389 Callback, 2390 bool AllowScopeSpecifier) { 2391 // Parse '('. 2392 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2393 if (T.expectAndConsume(diag::err_expected_lparen_after, 2394 getOpenMPDirectiveName(Kind).data())) 2395 return true; 2396 bool IsCorrect = true; 2397 bool NoIdentIsFound = true; 2398 2399 // Read tokens while ')' or annot_pragma_openmp_end is not found. 2400 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 2401 CXXScopeSpec SS; 2402 UnqualifiedId Name; 2403 // Read var name. 2404 Token PrevTok = Tok; 2405 NoIdentIsFound = false; 2406 2407 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 2408 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 2409 /*ObjectHadErrors=*/false, false)) { 2410 IsCorrect = false; 2411 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2412 StopBeforeMatch); 2413 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, 2414 /*ObjectHadErrors=*/false, false, false, 2415 false, false, nullptr, Name)) { 2416 IsCorrect = false; 2417 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2418 StopBeforeMatch); 2419 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 2420 Tok.isNot(tok::annot_pragma_openmp_end)) { 2421 IsCorrect = false; 2422 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2423 StopBeforeMatch); 2424 Diag(PrevTok.getLocation(), diag::err_expected) 2425 << tok::identifier 2426 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 2427 } else { 2428 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 2429 } 2430 // Consume ','. 2431 if (Tok.is(tok::comma)) { 2432 ConsumeToken(); 2433 } 2434 } 2435 2436 if (NoIdentIsFound) { 2437 Diag(Tok, diag::err_expected) << tok::identifier; 2438 IsCorrect = false; 2439 } 2440 2441 // Parse ')'. 2442 IsCorrect = !T.consumeClose() && IsCorrect; 2443 2444 return !IsCorrect; 2445 } 2446 2447 OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { 2448 SourceLocation Loc = Tok.getLocation(); 2449 ConsumeAnyToken(); 2450 2451 // Parse '('. 2452 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2453 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator")) 2454 return nullptr; 2455 SmallVector<Sema::UsesAllocatorsData, 4> Data; 2456 do { 2457 ExprResult Allocator = ParseCXXIdExpression(); 2458 if (Allocator.isInvalid()) { 2459 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2460 StopBeforeMatch); 2461 break; 2462 } 2463 Sema::UsesAllocatorsData &D = Data.emplace_back(); 2464 D.Allocator = Allocator.get(); 2465 if (Tok.is(tok::l_paren)) { 2466 BalancedDelimiterTracker T(*this, tok::l_paren, 2467 tok::annot_pragma_openmp_end); 2468 T.consumeOpen(); 2469 ExprResult AllocatorTraits = ParseCXXIdExpression(); 2470 T.consumeClose(); 2471 if (AllocatorTraits.isInvalid()) { 2472 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2473 StopBeforeMatch); 2474 break; 2475 } 2476 D.AllocatorTraits = AllocatorTraits.get(); 2477 D.LParenLoc = T.getOpenLocation(); 2478 D.RParenLoc = T.getCloseLocation(); 2479 } 2480 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 2481 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0; 2482 // Parse ',' 2483 if (Tok.is(tok::comma)) 2484 ConsumeAnyToken(); 2485 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); 2486 T.consumeClose(); 2487 return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(), 2488 T.getCloseLocation(), Data); 2489 } 2490 2491 /// Parsing of OpenMP clauses. 2492 /// 2493 /// clause: 2494 /// if-clause | final-clause | num_threads-clause | safelen-clause | 2495 /// default-clause | private-clause | firstprivate-clause | shared-clause 2496 /// | linear-clause | aligned-clause | collapse-clause | 2497 /// lastprivate-clause | reduction-clause | proc_bind-clause | 2498 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 2499 /// mergeable-clause | flush-clause | read-clause | write-clause | 2500 /// update-clause | capture-clause | seq_cst-clause | device-clause | 2501 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 2502 /// thread_limit-clause | priority-clause | grainsize-clause | 2503 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 2504 /// from-clause | is_device_ptr-clause | task_reduction-clause | 2505 /// in_reduction-clause | allocator-clause | allocate-clause | 2506 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | 2507 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause | 2508 /// exclusive-clause | uses_allocators-clause | use_device_addr-clause 2509 /// 2510 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 2511 OpenMPClauseKind CKind, bool FirstClause) { 2512 OMPClauseKind = CKind; 2513 OMPClause *Clause = nullptr; 2514 bool ErrorFound = false; 2515 bool WrongDirective = false; 2516 // Check if clause is allowed for the given directive. 2517 if (CKind != OMPC_unknown && 2518 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 2519 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 2520 << getOpenMPDirectiveName(DKind); 2521 ErrorFound = true; 2522 WrongDirective = true; 2523 } 2524 2525 switch (CKind) { 2526 case OMPC_final: 2527 case OMPC_num_threads: 2528 case OMPC_safelen: 2529 case OMPC_simdlen: 2530 case OMPC_collapse: 2531 case OMPC_ordered: 2532 case OMPC_num_teams: 2533 case OMPC_thread_limit: 2534 case OMPC_priority: 2535 case OMPC_grainsize: 2536 case OMPC_num_tasks: 2537 case OMPC_hint: 2538 case OMPC_allocator: 2539 case OMPC_depobj: 2540 case OMPC_detach: 2541 // OpenMP [2.5, Restrictions] 2542 // At most one num_threads clause can appear on the directive. 2543 // OpenMP [2.8.1, simd construct, Restrictions] 2544 // Only one safelen clause can appear on a simd directive. 2545 // Only one simdlen clause can appear on a simd directive. 2546 // Only one collapse clause can appear on a simd directive. 2547 // OpenMP [2.11.1, task Construct, Restrictions] 2548 // At most one if clause can appear on the directive. 2549 // At most one final clause can appear on the directive. 2550 // OpenMP [teams Construct, Restrictions] 2551 // At most one num_teams clause can appear on the directive. 2552 // At most one thread_limit clause can appear on the directive. 2553 // OpenMP [2.9.1, task Construct, Restrictions] 2554 // At most one priority clause can appear on the directive. 2555 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2556 // At most one grainsize clause can appear on the directive. 2557 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2558 // At most one num_tasks clause can appear on the directive. 2559 // OpenMP [2.11.3, allocate Directive, Restrictions] 2560 // At most one allocator clause can appear on the directive. 2561 // OpenMP 5.0, 2.10.1 task Construct, Restrictions. 2562 // At most one detach clause can appear on the directive. 2563 if (!FirstClause) { 2564 Diag(Tok, diag::err_omp_more_one_clause) 2565 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2566 ErrorFound = true; 2567 } 2568 2569 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 2570 Clause = ParseOpenMPClause(CKind, WrongDirective); 2571 else 2572 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 2573 break; 2574 case OMPC_default: 2575 case OMPC_proc_bind: 2576 case OMPC_atomic_default_mem_order: 2577 case OMPC_order: 2578 // OpenMP [2.14.3.1, Restrictions] 2579 // Only a single default clause may be specified on a parallel, task or 2580 // teams directive. 2581 // OpenMP [2.5, parallel Construct, Restrictions] 2582 // At most one proc_bind clause can appear on the directive. 2583 // OpenMP [5.0, Requires directive, Restrictions] 2584 // At most one atomic_default_mem_order clause can appear 2585 // on the directive 2586 if (!FirstClause && CKind != OMPC_order) { 2587 Diag(Tok, diag::err_omp_more_one_clause) 2588 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2589 ErrorFound = true; 2590 } 2591 2592 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 2593 break; 2594 case OMPC_device: 2595 case OMPC_schedule: 2596 case OMPC_dist_schedule: 2597 case OMPC_defaultmap: 2598 // OpenMP [2.7.1, Restrictions, p. 3] 2599 // Only one schedule clause can appear on a loop directive. 2600 // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 2601 // At most one defaultmap clause can appear on the directive. 2602 // OpenMP 5.0 [2.12.5, target construct, Restrictions] 2603 // At most one device clause can appear on the directive. 2604 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 2605 !FirstClause) { 2606 Diag(Tok, diag::err_omp_more_one_clause) 2607 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2608 ErrorFound = true; 2609 } 2610 LLVM_FALLTHROUGH; 2611 case OMPC_if: 2612 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); 2613 break; 2614 case OMPC_nowait: 2615 case OMPC_untied: 2616 case OMPC_mergeable: 2617 case OMPC_read: 2618 case OMPC_write: 2619 case OMPC_capture: 2620 case OMPC_seq_cst: 2621 case OMPC_acq_rel: 2622 case OMPC_acquire: 2623 case OMPC_release: 2624 case OMPC_relaxed: 2625 case OMPC_threads: 2626 case OMPC_simd: 2627 case OMPC_nogroup: 2628 case OMPC_unified_address: 2629 case OMPC_unified_shared_memory: 2630 case OMPC_reverse_offload: 2631 case OMPC_dynamic_allocators: 2632 case OMPC_destroy: 2633 // OpenMP [2.7.1, Restrictions, p. 9] 2634 // Only one ordered clause can appear on a loop directive. 2635 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 2636 // Only one nowait clause can appear on a for directive. 2637 // OpenMP [5.0, Requires directive, Restrictions] 2638 // Each of the requires clauses can appear at most once on the directive. 2639 if (!FirstClause) { 2640 Diag(Tok, diag::err_omp_more_one_clause) 2641 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2642 ErrorFound = true; 2643 } 2644 2645 Clause = ParseOpenMPClause(CKind, WrongDirective); 2646 break; 2647 case OMPC_update: 2648 if (!FirstClause) { 2649 Diag(Tok, diag::err_omp_more_one_clause) 2650 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2651 ErrorFound = true; 2652 } 2653 2654 Clause = (DKind == OMPD_depobj) 2655 ? ParseOpenMPSimpleClause(CKind, WrongDirective) 2656 : ParseOpenMPClause(CKind, WrongDirective); 2657 break; 2658 case OMPC_private: 2659 case OMPC_firstprivate: 2660 case OMPC_lastprivate: 2661 case OMPC_shared: 2662 case OMPC_reduction: 2663 case OMPC_task_reduction: 2664 case OMPC_in_reduction: 2665 case OMPC_linear: 2666 case OMPC_aligned: 2667 case OMPC_copyin: 2668 case OMPC_copyprivate: 2669 case OMPC_flush: 2670 case OMPC_depend: 2671 case OMPC_map: 2672 case OMPC_to: 2673 case OMPC_from: 2674 case OMPC_use_device_ptr: 2675 case OMPC_use_device_addr: 2676 case OMPC_is_device_ptr: 2677 case OMPC_allocate: 2678 case OMPC_nontemporal: 2679 case OMPC_inclusive: 2680 case OMPC_exclusive: 2681 case OMPC_affinity: 2682 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 2683 break; 2684 case OMPC_uses_allocators: 2685 Clause = ParseOpenMPUsesAllocatorClause(DKind); 2686 break; 2687 case OMPC_device_type: 2688 case OMPC_unknown: 2689 skipUntilPragmaOpenMPEnd(DKind); 2690 break; 2691 case OMPC_threadprivate: 2692 case OMPC_uniform: 2693 case OMPC_match: 2694 if (!WrongDirective) 2695 Diag(Tok, diag::err_omp_unexpected_clause) 2696 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 2697 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 2698 break; 2699 default: 2700 break; 2701 } 2702 return ErrorFound ? nullptr : Clause; 2703 } 2704 2705 /// Parses simple expression in parens for single-expression clauses of OpenMP 2706 /// constructs. 2707 /// \param RLoc Returned location of right paren. 2708 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 2709 SourceLocation &RLoc, 2710 bool IsAddressOfOperand) { 2711 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2712 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 2713 return ExprError(); 2714 2715 SourceLocation ELoc = Tok.getLocation(); 2716 ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand, 2717 NotTypeCast)); 2718 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 2719 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2720 2721 // Parse ')'. 2722 RLoc = Tok.getLocation(); 2723 if (!T.consumeClose()) 2724 RLoc = T.getCloseLocation(); 2725 2726 return Val; 2727 } 2728 2729 /// Parsing of OpenMP clauses with single expressions like 'final', 2730 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 2731 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or 2732 /// 'detach'. 2733 /// 2734 /// final-clause: 2735 /// 'final' '(' expression ')' 2736 /// 2737 /// num_threads-clause: 2738 /// 'num_threads' '(' expression ')' 2739 /// 2740 /// safelen-clause: 2741 /// 'safelen' '(' expression ')' 2742 /// 2743 /// simdlen-clause: 2744 /// 'simdlen' '(' expression ')' 2745 /// 2746 /// collapse-clause: 2747 /// 'collapse' '(' expression ')' 2748 /// 2749 /// priority-clause: 2750 /// 'priority' '(' expression ')' 2751 /// 2752 /// grainsize-clause: 2753 /// 'grainsize' '(' expression ')' 2754 /// 2755 /// num_tasks-clause: 2756 /// 'num_tasks' '(' expression ')' 2757 /// 2758 /// hint-clause: 2759 /// 'hint' '(' expression ')' 2760 /// 2761 /// allocator-clause: 2762 /// 'allocator' '(' expression ')' 2763 /// 2764 /// detach-clause: 2765 /// 'detach' '(' event-handler-expression ')' 2766 /// 2767 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 2768 bool ParseOnly) { 2769 SourceLocation Loc = ConsumeToken(); 2770 SourceLocation LLoc = Tok.getLocation(); 2771 SourceLocation RLoc; 2772 2773 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 2774 2775 if (Val.isInvalid()) 2776 return nullptr; 2777 2778 if (ParseOnly) 2779 return nullptr; 2780 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 2781 } 2782 2783 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 2784 /// 2785 /// default-clause: 2786 /// 'default' '(' 'none' | 'shared' | 'firstprivate' ')' 2787 /// 2788 /// proc_bind-clause: 2789 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' 2790 /// 2791 /// update-clause: 2792 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')' 2793 /// 2794 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 2795 bool ParseOnly) { 2796 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 2797 if (!Val || ParseOnly) 2798 return nullptr; 2799 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default && 2800 static_cast<DefaultKind>(Val.getValue().Type) == 2801 OMP_DEFAULT_firstprivate) { 2802 Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa) 2803 << getOpenMPClauseName(OMPC_firstprivate) 2804 << getOpenMPClauseName(OMPC_default) << "5.1"; 2805 return nullptr; 2806 } 2807 return Actions.ActOnOpenMPSimpleClause( 2808 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, 2809 Val.getValue().Loc, Val.getValue().RLoc); 2810 } 2811 2812 /// Parsing of OpenMP clauses like 'ordered'. 2813 /// 2814 /// ordered-clause: 2815 /// 'ordered' 2816 /// 2817 /// nowait-clause: 2818 /// 'nowait' 2819 /// 2820 /// untied-clause: 2821 /// 'untied' 2822 /// 2823 /// mergeable-clause: 2824 /// 'mergeable' 2825 /// 2826 /// read-clause: 2827 /// 'read' 2828 /// 2829 /// threads-clause: 2830 /// 'threads' 2831 /// 2832 /// simd-clause: 2833 /// 'simd' 2834 /// 2835 /// nogroup-clause: 2836 /// 'nogroup' 2837 /// 2838 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 2839 SourceLocation Loc = Tok.getLocation(); 2840 ConsumeAnyToken(); 2841 2842 if (ParseOnly) 2843 return nullptr; 2844 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 2845 } 2846 2847 /// Parsing of OpenMP clauses with single expressions and some additional 2848 /// argument like 'schedule' or 'dist_schedule'. 2849 /// 2850 /// schedule-clause: 2851 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 2852 /// ')' 2853 /// 2854 /// if-clause: 2855 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 2856 /// 2857 /// defaultmap: 2858 /// 'defaultmap' '(' modifier [ ':' kind ] ')' 2859 /// 2860 /// device-clause: 2861 /// 'device' '(' [ device-modifier ':' ] expression ')' 2862 /// 2863 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, 2864 OpenMPClauseKind Kind, 2865 bool ParseOnly) { 2866 SourceLocation Loc = ConsumeToken(); 2867 SourceLocation DelimLoc; 2868 // Parse '('. 2869 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2870 if (T.expectAndConsume(diag::err_expected_lparen_after, 2871 getOpenMPClauseName(Kind).data())) 2872 return nullptr; 2873 2874 ExprResult Val; 2875 SmallVector<unsigned, 4> Arg; 2876 SmallVector<SourceLocation, 4> KLoc; 2877 if (Kind == OMPC_schedule) { 2878 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 2879 Arg.resize(NumberOfElements); 2880 KLoc.resize(NumberOfElements); 2881 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 2882 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 2883 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 2884 unsigned KindModifier = getOpenMPSimpleClauseType( 2885 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2886 getLangOpts().OpenMP); 2887 if (KindModifier > OMPC_SCHEDULE_unknown) { 2888 // Parse 'modifier' 2889 Arg[Modifier1] = KindModifier; 2890 KLoc[Modifier1] = Tok.getLocation(); 2891 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2892 Tok.isNot(tok::annot_pragma_openmp_end)) 2893 ConsumeAnyToken(); 2894 if (Tok.is(tok::comma)) { 2895 // Parse ',' 'modifier' 2896 ConsumeAnyToken(); 2897 KindModifier = getOpenMPSimpleClauseType( 2898 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2899 getLangOpts().OpenMP); 2900 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 2901 ? KindModifier 2902 : (unsigned)OMPC_SCHEDULE_unknown; 2903 KLoc[Modifier2] = Tok.getLocation(); 2904 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2905 Tok.isNot(tok::annot_pragma_openmp_end)) 2906 ConsumeAnyToken(); 2907 } 2908 // Parse ':' 2909 if (Tok.is(tok::colon)) 2910 ConsumeAnyToken(); 2911 else 2912 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 2913 KindModifier = getOpenMPSimpleClauseType( 2914 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2915 getLangOpts().OpenMP); 2916 } 2917 Arg[ScheduleKind] = KindModifier; 2918 KLoc[ScheduleKind] = Tok.getLocation(); 2919 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2920 Tok.isNot(tok::annot_pragma_openmp_end)) 2921 ConsumeAnyToken(); 2922 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 2923 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 2924 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 2925 Tok.is(tok::comma)) 2926 DelimLoc = ConsumeAnyToken(); 2927 } else if (Kind == OMPC_dist_schedule) { 2928 Arg.push_back(getOpenMPSimpleClauseType( 2929 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2930 getLangOpts().OpenMP)); 2931 KLoc.push_back(Tok.getLocation()); 2932 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2933 Tok.isNot(tok::annot_pragma_openmp_end)) 2934 ConsumeAnyToken(); 2935 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 2936 DelimLoc = ConsumeAnyToken(); 2937 } else if (Kind == OMPC_defaultmap) { 2938 // Get a defaultmap modifier 2939 unsigned Modifier = getOpenMPSimpleClauseType( 2940 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2941 getLangOpts().OpenMP); 2942 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 2943 // pointer 2944 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 2945 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 2946 Arg.push_back(Modifier); 2947 KLoc.push_back(Tok.getLocation()); 2948 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2949 Tok.isNot(tok::annot_pragma_openmp_end)) 2950 ConsumeAnyToken(); 2951 // Parse ':' 2952 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) { 2953 if (Tok.is(tok::colon)) 2954 ConsumeAnyToken(); 2955 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 2956 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 2957 // Get a defaultmap kind 2958 Arg.push_back(getOpenMPSimpleClauseType( 2959 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2960 getLangOpts().OpenMP)); 2961 KLoc.push_back(Tok.getLocation()); 2962 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2963 Tok.isNot(tok::annot_pragma_openmp_end)) 2964 ConsumeAnyToken(); 2965 } else { 2966 Arg.push_back(OMPC_DEFAULTMAP_unknown); 2967 KLoc.push_back(SourceLocation()); 2968 } 2969 } else if (Kind == OMPC_device) { 2970 // Only target executable directives support extended device construct. 2971 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 && 2972 NextToken().is(tok::colon)) { 2973 // Parse optional <device modifier> ':' 2974 Arg.push_back(getOpenMPSimpleClauseType( 2975 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 2976 getLangOpts().OpenMP)); 2977 KLoc.push_back(Tok.getLocation()); 2978 ConsumeAnyToken(); 2979 // Parse ':' 2980 ConsumeAnyToken(); 2981 } else { 2982 Arg.push_back(OMPC_DEVICE_unknown); 2983 KLoc.emplace_back(); 2984 } 2985 } else { 2986 assert(Kind == OMPC_if); 2987 KLoc.push_back(Tok.getLocation()); 2988 TentativeParsingAction TPA(*this); 2989 auto DK = parseOpenMPDirectiveKind(*this); 2990 Arg.push_back(DK); 2991 if (DK != OMPD_unknown) { 2992 ConsumeToken(); 2993 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 2994 TPA.Commit(); 2995 DelimLoc = ConsumeToken(); 2996 } else { 2997 TPA.Revert(); 2998 Arg.back() = unsigned(OMPD_unknown); 2999 } 3000 } else { 3001 TPA.Revert(); 3002 } 3003 } 3004 3005 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 3006 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 3007 Kind == OMPC_if || Kind == OMPC_device; 3008 if (NeedAnExpression) { 3009 SourceLocation ELoc = Tok.getLocation(); 3010 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 3011 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 3012 Val = 3013 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3014 } 3015 3016 // Parse ')'. 3017 SourceLocation RLoc = Tok.getLocation(); 3018 if (!T.consumeClose()) 3019 RLoc = T.getCloseLocation(); 3020 3021 if (NeedAnExpression && Val.isInvalid()) 3022 return nullptr; 3023 3024 if (ParseOnly) 3025 return nullptr; 3026 return Actions.ActOnOpenMPSingleExprWithArgClause( 3027 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 3028 } 3029 3030 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 3031 UnqualifiedId &ReductionId) { 3032 if (ReductionIdScopeSpec.isEmpty()) { 3033 auto OOK = OO_None; 3034 switch (P.getCurToken().getKind()) { 3035 case tok::plus: 3036 OOK = OO_Plus; 3037 break; 3038 case tok::minus: 3039 OOK = OO_Minus; 3040 break; 3041 case tok::star: 3042 OOK = OO_Star; 3043 break; 3044 case tok::amp: 3045 OOK = OO_Amp; 3046 break; 3047 case tok::pipe: 3048 OOK = OO_Pipe; 3049 break; 3050 case tok::caret: 3051 OOK = OO_Caret; 3052 break; 3053 case tok::ampamp: 3054 OOK = OO_AmpAmp; 3055 break; 3056 case tok::pipepipe: 3057 OOK = OO_PipePipe; 3058 break; 3059 default: 3060 break; 3061 } 3062 if (OOK != OO_None) { 3063 SourceLocation OpLoc = P.ConsumeToken(); 3064 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 3065 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 3066 return false; 3067 } 3068 } 3069 return P.ParseUnqualifiedId( 3070 ReductionIdScopeSpec, /*ObjectType=*/nullptr, 3071 /*ObjectHadErrors=*/false, /*EnteringContext*/ false, 3072 /*AllowDestructorName*/ false, 3073 /*AllowConstructorName*/ false, 3074 /*AllowDeductionGuide*/ false, nullptr, ReductionId); 3075 } 3076 3077 /// Checks if the token is a valid map-type-modifier. 3078 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses. 3079 static OpenMPMapModifierKind isMapModifier(Parser &P) { 3080 Token Tok = P.getCurToken(); 3081 if (!Tok.is(tok::identifier)) 3082 return OMPC_MAP_MODIFIER_unknown; 3083 3084 Preprocessor &PP = P.getPreprocessor(); 3085 OpenMPMapModifierKind TypeModifier = 3086 static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType( 3087 OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP)); 3088 return TypeModifier; 3089 } 3090 3091 /// Parse the mapper modifier in map, to, and from clauses. 3092 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 3093 // Parse '('. 3094 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 3095 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 3096 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3097 StopBeforeMatch); 3098 return true; 3099 } 3100 // Parse mapper-identifier 3101 if (getLangOpts().CPlusPlus) 3102 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3103 /*ObjectType=*/nullptr, 3104 /*ObjectHadErrors=*/false, 3105 /*EnteringContext=*/false); 3106 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 3107 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 3108 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3109 StopBeforeMatch); 3110 return true; 3111 } 3112 auto &DeclNames = Actions.getASTContext().DeclarationNames; 3113 Data.ReductionOrMapperId = DeclarationNameInfo( 3114 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 3115 ConsumeToken(); 3116 // Parse ')'. 3117 return T.consumeClose(); 3118 } 3119 3120 /// Parse map-type-modifiers in map clause. 3121 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3122 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) | 3123 /// present 3124 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 3125 while (getCurToken().isNot(tok::colon)) { 3126 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 3127 if (TypeModifier == OMPC_MAP_MODIFIER_always || 3128 TypeModifier == OMPC_MAP_MODIFIER_close || 3129 TypeModifier == OMPC_MAP_MODIFIER_present) { 3130 Data.MapTypeModifiers.push_back(TypeModifier); 3131 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3132 ConsumeToken(); 3133 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 3134 Data.MapTypeModifiers.push_back(TypeModifier); 3135 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3136 ConsumeToken(); 3137 if (parseMapperModifier(Data)) 3138 return true; 3139 } else { 3140 // For the case of unknown map-type-modifier or a map-type. 3141 // Map-type is followed by a colon; the function returns when it 3142 // encounters a token followed by a colon. 3143 if (Tok.is(tok::comma)) { 3144 Diag(Tok, diag::err_omp_map_type_modifier_missing); 3145 ConsumeToken(); 3146 continue; 3147 } 3148 // Potential map-type token as it is followed by a colon. 3149 if (PP.LookAhead(0).is(tok::colon)) 3150 return false; 3151 Diag(Tok, diag::err_omp_unknown_map_type_modifier) 3152 << (getLangOpts().OpenMP >= 51 ? 1 : 0); 3153 ConsumeToken(); 3154 } 3155 if (getCurToken().is(tok::comma)) 3156 ConsumeToken(); 3157 } 3158 return false; 3159 } 3160 3161 /// Checks if the token is a valid map-type. 3162 /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses. 3163 static OpenMPMapClauseKind isMapType(Parser &P) { 3164 Token Tok = P.getCurToken(); 3165 // The map-type token can be either an identifier or the C++ delete keyword. 3166 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 3167 return OMPC_MAP_unknown; 3168 Preprocessor &PP = P.getPreprocessor(); 3169 OpenMPMapClauseKind MapType = 3170 static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 3171 OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP)); 3172 return MapType; 3173 } 3174 3175 /// Parse map-type in map clause. 3176 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3177 /// where, map-type ::= to | from | tofrom | alloc | release | delete 3178 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 3179 Token Tok = P.getCurToken(); 3180 if (Tok.is(tok::colon)) { 3181 P.Diag(Tok, diag::err_omp_map_type_missing); 3182 return; 3183 } 3184 Data.ExtraModifier = isMapType(P); 3185 if (Data.ExtraModifier == OMPC_MAP_unknown) 3186 P.Diag(Tok, diag::err_omp_unknown_map_type); 3187 P.ConsumeToken(); 3188 } 3189 3190 /// Parses simple expression in parens for single-expression clauses of OpenMP 3191 /// constructs. 3192 ExprResult Parser::ParseOpenMPIteratorsExpr() { 3193 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" && 3194 "Expected 'iterator' token."); 3195 SourceLocation IteratorKwLoc = ConsumeToken(); 3196 3197 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3198 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator")) 3199 return ExprError(); 3200 3201 SourceLocation LLoc = T.getOpenLocation(); 3202 SmallVector<Sema::OMPIteratorData, 4> Data; 3203 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 3204 // Check if the type parsing is required. 3205 ParsedType IteratorType; 3206 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) { 3207 // identifier '=' is not found - parse type. 3208 TypeResult TR = ParseTypeName(); 3209 if (TR.isInvalid()) { 3210 T.skipToEnd(); 3211 return ExprError(); 3212 } 3213 IteratorType = TR.get(); 3214 } 3215 3216 // Parse identifier. 3217 IdentifierInfo *II = nullptr; 3218 SourceLocation IdLoc; 3219 if (Tok.is(tok::identifier)) { 3220 II = Tok.getIdentifierInfo(); 3221 IdLoc = ConsumeToken(); 3222 } else { 3223 Diag(Tok, diag::err_expected_unqualified_id) << 0; 3224 } 3225 3226 // Parse '='. 3227 SourceLocation AssignLoc; 3228 if (Tok.is(tok::equal)) 3229 AssignLoc = ConsumeToken(); 3230 else 3231 Diag(Tok, diag::err_omp_expected_equal_in_iterator); 3232 3233 // Parse range-specification - <begin> ':' <end> [ ':' <step> ] 3234 ColonProtectionRAIIObject ColonRAII(*this); 3235 // Parse <begin> 3236 SourceLocation Loc = Tok.getLocation(); 3237 ExprResult LHS = ParseCastExpression(AnyCastExpr); 3238 ExprResult Begin = Actions.CorrectDelayedTyposInExpr( 3239 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3240 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc, 3241 /*DiscardedValue=*/false); 3242 // Parse ':'. 3243 SourceLocation ColonLoc; 3244 if (Tok.is(tok::colon)) 3245 ColonLoc = ConsumeToken(); 3246 3247 // Parse <end> 3248 Loc = Tok.getLocation(); 3249 LHS = ParseCastExpression(AnyCastExpr); 3250 ExprResult End = Actions.CorrectDelayedTyposInExpr( 3251 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3252 End = Actions.ActOnFinishFullExpr(End.get(), Loc, 3253 /*DiscardedValue=*/false); 3254 3255 SourceLocation SecColonLoc; 3256 ExprResult Step; 3257 // Parse optional step. 3258 if (Tok.is(tok::colon)) { 3259 // Parse ':' 3260 SecColonLoc = ConsumeToken(); 3261 // Parse <step> 3262 Loc = Tok.getLocation(); 3263 LHS = ParseCastExpression(AnyCastExpr); 3264 Step = Actions.CorrectDelayedTyposInExpr( 3265 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3266 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc, 3267 /*DiscardedValue=*/false); 3268 } 3269 3270 // Parse ',' or ')' 3271 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 3272 Diag(Tok, diag::err_omp_expected_punc_after_iterator); 3273 if (Tok.is(tok::comma)) 3274 ConsumeToken(); 3275 3276 Sema::OMPIteratorData &D = Data.emplace_back(); 3277 D.DeclIdent = II; 3278 D.DeclIdentLoc = IdLoc; 3279 D.Type = IteratorType; 3280 D.AssignLoc = AssignLoc; 3281 D.ColonLoc = ColonLoc; 3282 D.SecColonLoc = SecColonLoc; 3283 D.Range.Begin = Begin.get(); 3284 D.Range.End = End.get(); 3285 D.Range.Step = Step.get(); 3286 } 3287 3288 // Parse ')'. 3289 SourceLocation RLoc = Tok.getLocation(); 3290 if (!T.consumeClose()) 3291 RLoc = T.getCloseLocation(); 3292 3293 return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc, 3294 Data); 3295 } 3296 3297 /// Parses clauses with list. 3298 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 3299 OpenMPClauseKind Kind, 3300 SmallVectorImpl<Expr *> &Vars, 3301 OpenMPVarListDataTy &Data) { 3302 UnqualifiedId UnqualifiedReductionId; 3303 bool InvalidReductionId = false; 3304 bool IsInvalidMapperModifier = false; 3305 3306 // Parse '('. 3307 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3308 if (T.expectAndConsume(diag::err_expected_lparen_after, 3309 getOpenMPClauseName(Kind).data())) 3310 return true; 3311 3312 bool HasIterator = false; 3313 bool NeedRParenForLinear = false; 3314 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 3315 tok::annot_pragma_openmp_end); 3316 // Handle reduction-identifier for reduction clause. 3317 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 3318 Kind == OMPC_in_reduction) { 3319 Data.ExtraModifier = OMPC_REDUCTION_unknown; 3320 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 && 3321 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) && 3322 NextToken().is(tok::comma)) { 3323 // Parse optional reduction modifier. 3324 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), 3325 getLangOpts().OpenMP); 3326 Data.ExtraModifierLoc = Tok.getLocation(); 3327 ConsumeToken(); 3328 assert(Tok.is(tok::comma) && "Expected comma."); 3329 (void)ConsumeToken(); 3330 } 3331 ColonProtectionRAIIObject ColonRAII(*this); 3332 if (getLangOpts().CPlusPlus) 3333 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3334 /*ObjectType=*/nullptr, 3335 /*ObjectHadErrors=*/false, 3336 /*EnteringContext=*/false); 3337 InvalidReductionId = ParseReductionId( 3338 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 3339 if (InvalidReductionId) { 3340 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3341 StopBeforeMatch); 3342 } 3343 if (Tok.is(tok::colon)) 3344 Data.ColonLoc = ConsumeToken(); 3345 else 3346 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 3347 if (!InvalidReductionId) 3348 Data.ReductionOrMapperId = 3349 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 3350 } else if (Kind == OMPC_depend) { 3351 if (getLangOpts().OpenMP >= 50) { 3352 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { 3353 // Handle optional dependence modifier. 3354 // iterator(iterators-definition) 3355 // where iterators-definition is iterator-specifier [, 3356 // iterators-definition ] 3357 // where iterator-specifier is [ iterator-type ] identifier = 3358 // range-specification 3359 HasIterator = true; 3360 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 3361 ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); 3362 Data.DepModOrTailExpr = IteratorRes.get(); 3363 // Parse ',' 3364 ExpectAndConsume(tok::comma); 3365 } 3366 } 3367 // Handle dependency type for depend clause. 3368 ColonProtectionRAIIObject ColonRAII(*this); 3369 Data.ExtraModifier = getOpenMPSimpleClauseType( 3370 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 3371 getLangOpts().OpenMP); 3372 Data.ExtraModifierLoc = Tok.getLocation(); 3373 if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 3374 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3375 StopBeforeMatch); 3376 } else { 3377 ConsumeToken(); 3378 // Special processing for depend(source) clause. 3379 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 3380 // Parse ')'. 3381 T.consumeClose(); 3382 return false; 3383 } 3384 } 3385 if (Tok.is(tok::colon)) { 3386 Data.ColonLoc = ConsumeToken(); 3387 } else { 3388 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 3389 : diag::warn_pragma_expected_colon) 3390 << "dependency type"; 3391 } 3392 } else if (Kind == OMPC_linear) { 3393 // Try to parse modifier if any. 3394 Data.ExtraModifier = OMPC_LINEAR_val; 3395 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 3396 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), 3397 getLangOpts().OpenMP); 3398 Data.ExtraModifierLoc = ConsumeToken(); 3399 LinearT.consumeOpen(); 3400 NeedRParenForLinear = true; 3401 } 3402 } else if (Kind == OMPC_lastprivate) { 3403 // Try to parse modifier if any. 3404 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 3405 // Conditional modifier allowed only in OpenMP 5.0 and not supported in 3406 // distribute and taskloop based directives. 3407 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 3408 !isOpenMPTaskLoopDirective(DKind)) && 3409 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 3410 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), 3411 getLangOpts().OpenMP); 3412 Data.ExtraModifierLoc = Tok.getLocation(); 3413 ConsumeToken(); 3414 assert(Tok.is(tok::colon) && "Expected colon."); 3415 Data.ColonLoc = ConsumeToken(); 3416 } 3417 } else if (Kind == OMPC_map) { 3418 // Handle map type for map clause. 3419 ColonProtectionRAIIObject ColonRAII(*this); 3420 3421 // The first identifier may be a list item, a map-type or a 3422 // map-type-modifier. The map-type can also be delete which has the same 3423 // spelling of the C++ delete keyword. 3424 Data.ExtraModifier = OMPC_MAP_unknown; 3425 Data.ExtraModifierLoc = Tok.getLocation(); 3426 3427 // Check for presence of a colon in the map clause. 3428 TentativeParsingAction TPA(*this); 3429 bool ColonPresent = false; 3430 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3431 StopBeforeMatch)) { 3432 if (Tok.is(tok::colon)) 3433 ColonPresent = true; 3434 } 3435 TPA.Revert(); 3436 // Only parse map-type-modifier[s] and map-type if a colon is present in 3437 // the map clause. 3438 if (ColonPresent) { 3439 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 3440 if (!IsInvalidMapperModifier) 3441 parseMapType(*this, Data); 3442 else 3443 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 3444 } 3445 if (Data.ExtraModifier == OMPC_MAP_unknown) { 3446 Data.ExtraModifier = OMPC_MAP_tofrom; 3447 Data.IsMapTypeImplicit = true; 3448 } 3449 3450 if (Tok.is(tok::colon)) 3451 Data.ColonLoc = ConsumeToken(); 3452 } else if (Kind == OMPC_to || Kind == OMPC_from) { 3453 while (Tok.is(tok::identifier)) { 3454 auto Modifier = 3455 static_cast<OpenMPMotionModifierKind>(getOpenMPSimpleClauseType( 3456 Kind, PP.getSpelling(Tok), getLangOpts().OpenMP)); 3457 if (Modifier == OMPC_MOTION_MODIFIER_unknown) 3458 break; 3459 Data.MotionModifiers.push_back(Modifier); 3460 Data.MotionModifiersLoc.push_back(Tok.getLocation()); 3461 ConsumeToken(); 3462 if (Modifier == OMPC_MOTION_MODIFIER_mapper) { 3463 IsInvalidMapperModifier = parseMapperModifier(Data); 3464 if (IsInvalidMapperModifier) 3465 break; 3466 } 3467 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers. 3468 if (getLangOpts().OpenMP < 51) 3469 break; 3470 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'. 3471 // TODO: Is that intentional? 3472 if (Tok.is(tok::comma)) 3473 ConsumeToken(); 3474 } 3475 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) { 3476 if (!IsInvalidMapperModifier) { 3477 if (getLangOpts().OpenMP < 51) 3478 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 3479 else 3480 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier"; 3481 } 3482 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3483 StopBeforeMatch); 3484 } 3485 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is 3486 // that intentional? 3487 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) && 3488 Tok.is(tok::colon)) 3489 Data.ColonLoc = ConsumeToken(); 3490 } else if (Kind == OMPC_allocate || 3491 (Kind == OMPC_affinity && Tok.is(tok::identifier) && 3492 PP.getSpelling(Tok) == "iterator")) { 3493 // Handle optional allocator expression followed by colon delimiter. 3494 ColonProtectionRAIIObject ColonRAII(*this); 3495 TentativeParsingAction TPA(*this); 3496 // OpenMP 5.0, 2.10.1, task Construct. 3497 // where aff-modifier is one of the following: 3498 // iterator(iterators-definition) 3499 ExprResult Tail; 3500 if (Kind == OMPC_allocate) { 3501 Tail = ParseAssignmentExpression(); 3502 } else { 3503 HasIterator = true; 3504 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 3505 Tail = ParseOpenMPIteratorsExpr(); 3506 } 3507 Tail = Actions.CorrectDelayedTyposInExpr(Tail); 3508 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 3509 /*DiscardedValue=*/false); 3510 if (Tail.isUsable()) { 3511 if (Tok.is(tok::colon)) { 3512 Data.DepModOrTailExpr = Tail.get(); 3513 Data.ColonLoc = ConsumeToken(); 3514 TPA.Commit(); 3515 } else { 3516 // Colon not found, parse only list of variables. 3517 TPA.Revert(); 3518 } 3519 } else { 3520 // Parsing was unsuccessfull, revert and skip to the end of clause or 3521 // directive. 3522 TPA.Revert(); 3523 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3524 StopBeforeMatch); 3525 } 3526 } 3527 3528 bool IsComma = 3529 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 3530 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 3531 (Kind == OMPC_reduction && !InvalidReductionId) || 3532 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 3533 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown); 3534 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 3535 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 3536 Tok.isNot(tok::annot_pragma_openmp_end))) { 3537 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); 3538 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 3539 // Parse variable 3540 ExprResult VarExpr = 3541 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 3542 if (VarExpr.isUsable()) { 3543 Vars.push_back(VarExpr.get()); 3544 } else { 3545 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3546 StopBeforeMatch); 3547 } 3548 // Skip ',' if any 3549 IsComma = Tok.is(tok::comma); 3550 if (IsComma) 3551 ConsumeToken(); 3552 else if (Tok.isNot(tok::r_paren) && 3553 Tok.isNot(tok::annot_pragma_openmp_end) && 3554 (!MayHaveTail || Tok.isNot(tok::colon))) 3555 Diag(Tok, diag::err_omp_expected_punc) 3556 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 3557 : getOpenMPClauseName(Kind)) 3558 << (Kind == OMPC_flush); 3559 } 3560 3561 // Parse ')' for linear clause with modifier. 3562 if (NeedRParenForLinear) 3563 LinearT.consumeClose(); 3564 3565 // Parse ':' linear-step (or ':' alignment). 3566 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 3567 if (MustHaveTail) { 3568 Data.ColonLoc = Tok.getLocation(); 3569 SourceLocation ELoc = ConsumeToken(); 3570 ExprResult Tail = ParseAssignmentExpression(); 3571 Tail = 3572 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 3573 if (Tail.isUsable()) 3574 Data.DepModOrTailExpr = Tail.get(); 3575 else 3576 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3577 StopBeforeMatch); 3578 } 3579 3580 // Parse ')'. 3581 Data.RLoc = Tok.getLocation(); 3582 if (!T.consumeClose()) 3583 Data.RLoc = T.getCloseLocation(); 3584 // Exit from scope when the iterator is used in depend clause. 3585 if (HasIterator) 3586 ExitScope(); 3587 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 3588 (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || 3589 IsInvalidMapperModifier; 3590 } 3591 3592 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 3593 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction', 3594 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'. 3595 /// 3596 /// private-clause: 3597 /// 'private' '(' list ')' 3598 /// firstprivate-clause: 3599 /// 'firstprivate' '(' list ')' 3600 /// lastprivate-clause: 3601 /// 'lastprivate' '(' list ')' 3602 /// shared-clause: 3603 /// 'shared' '(' list ')' 3604 /// linear-clause: 3605 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 3606 /// aligned-clause: 3607 /// 'aligned' '(' list [ ':' alignment ] ')' 3608 /// reduction-clause: 3609 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')' 3610 /// task_reduction-clause: 3611 /// 'task_reduction' '(' reduction-identifier ':' list ')' 3612 /// in_reduction-clause: 3613 /// 'in_reduction' '(' reduction-identifier ':' list ')' 3614 /// copyprivate-clause: 3615 /// 'copyprivate' '(' list ')' 3616 /// flush-clause: 3617 /// 'flush' '(' list ')' 3618 /// depend-clause: 3619 /// 'depend' '(' in | out | inout : list | source ')' 3620 /// map-clause: 3621 /// 'map' '(' [ [ always [,] ] [ close [,] ] 3622 /// [ mapper '(' mapper-identifier ')' [,] ] 3623 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 3624 /// to-clause: 3625 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 3626 /// from-clause: 3627 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 3628 /// use_device_ptr-clause: 3629 /// 'use_device_ptr' '(' list ')' 3630 /// use_device_addr-clause: 3631 /// 'use_device_addr' '(' list ')' 3632 /// is_device_ptr-clause: 3633 /// 'is_device_ptr' '(' list ')' 3634 /// allocate-clause: 3635 /// 'allocate' '(' [ allocator ':' ] list ')' 3636 /// nontemporal-clause: 3637 /// 'nontemporal' '(' list ')' 3638 /// inclusive-clause: 3639 /// 'inclusive' '(' list ')' 3640 /// exclusive-clause: 3641 /// 'exclusive' '(' list ')' 3642 /// 3643 /// For 'linear' clause linear-list may have the following forms: 3644 /// list 3645 /// modifier(list) 3646 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 3647 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 3648 OpenMPClauseKind Kind, 3649 bool ParseOnly) { 3650 SourceLocation Loc = Tok.getLocation(); 3651 SourceLocation LOpen = ConsumeToken(); 3652 SmallVector<Expr *, 4> Vars; 3653 OpenMPVarListDataTy Data; 3654 3655 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 3656 return nullptr; 3657 3658 if (ParseOnly) 3659 return nullptr; 3660 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 3661 return Actions.ActOnOpenMPVarListClause( 3662 Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc, 3663 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 3664 Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 3665 Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers, 3666 Data.MotionModifiersLoc); 3667 } 3668 3669