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/StringSwitch.h" 25 #include "llvm/ADT/UniqueVector.h" 26 #include "llvm/Frontend/OpenMP/OMPAssume.h" 27 #include "llvm/Frontend/OpenMP/OMPContext.h" 28 #include <optional> 29 30 using namespace clang; 31 using namespace llvm::omp; 32 33 //===----------------------------------------------------------------------===// 34 // OpenMP declarative directives. 35 //===----------------------------------------------------------------------===// 36 37 namespace { 38 enum OpenMPDirectiveKindEx { 39 OMPD_cancellation = llvm::omp::Directive_enumSize + 1, 40 OMPD_data, 41 OMPD_declare, 42 OMPD_end, 43 OMPD_end_declare, 44 OMPD_enter, 45 OMPD_exit, 46 OMPD_point, 47 OMPD_reduction, 48 OMPD_target_enter, 49 OMPD_target_exit, 50 OMPD_update, 51 OMPD_distribute_parallel, 52 OMPD_teams_distribute_parallel, 53 OMPD_target_teams_distribute_parallel, 54 OMPD_mapper, 55 OMPD_variant, 56 OMPD_begin, 57 OMPD_begin_declare, 58 }; 59 60 // Helper to unify the enum class OpenMPDirectiveKind with its extension 61 // the OpenMPDirectiveKindEx enum which allows to use them together as if they 62 // are unsigned values. 63 struct OpenMPDirectiveKindExWrapper { 64 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {} 65 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {} 66 bool operator==(OpenMPDirectiveKindExWrapper V) const { 67 return Value == V.Value; 68 } 69 bool operator!=(OpenMPDirectiveKindExWrapper V) const { 70 return Value != V.Value; 71 } 72 bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); } 73 bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); } 74 bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); } 75 operator unsigned() const { return Value; } 76 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); } 77 unsigned Value; 78 }; 79 80 class DeclDirectiveListParserHelper final { 81 SmallVector<Expr *, 4> Identifiers; 82 Parser *P; 83 OpenMPDirectiveKind Kind; 84 85 public: 86 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) 87 : P(P), Kind(Kind) {} 88 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 89 ExprResult Res = P->getActions().ActOnOpenMPIdExpression( 90 P->getCurScope(), SS, NameInfo, Kind); 91 if (Res.isUsable()) 92 Identifiers.push_back(Res.get()); 93 } 94 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 95 }; 96 } // namespace 97 98 // Map token string to extended OMP token kind that are 99 // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 100 static unsigned getOpenMPDirectiveKindEx(StringRef S) { 101 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S); 102 if (DKind != OMPD_unknown) 103 return DKind; 104 105 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S) 106 .Case("cancellation", OMPD_cancellation) 107 .Case("data", OMPD_data) 108 .Case("declare", OMPD_declare) 109 .Case("end", OMPD_end) 110 .Case("enter", OMPD_enter) 111 .Case("exit", OMPD_exit) 112 .Case("point", OMPD_point) 113 .Case("reduction", OMPD_reduction) 114 .Case("update", OMPD_update) 115 .Case("mapper", OMPD_mapper) 116 .Case("variant", OMPD_variant) 117 .Case("begin", OMPD_begin) 118 .Default(OMPD_unknown); 119 } 120 121 static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { 122 // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 123 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 124 // TODO: add other combined directives in topological order. 125 static const OpenMPDirectiveKindExWrapper F[][3] = { 126 {OMPD_begin, OMPD_declare, OMPD_begin_declare}, 127 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes}, 128 {OMPD_end, OMPD_declare, OMPD_end_declare}, 129 {OMPD_end, OMPD_assumes, OMPD_end_assumes}, 130 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 131 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 132 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, 133 {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 134 {OMPD_declare, OMPD_target, OMPD_declare_target}, 135 {OMPD_declare, OMPD_variant, OMPD_declare_variant}, 136 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target}, 137 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant}, 138 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant}, 139 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 140 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 141 {OMPD_distribute_parallel_for, OMPD_simd, 142 OMPD_distribute_parallel_for_simd}, 143 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 144 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 145 {OMPD_target, OMPD_data, OMPD_target_data}, 146 {OMPD_target, OMPD_enter, OMPD_target_enter}, 147 {OMPD_target, OMPD_exit, OMPD_target_exit}, 148 {OMPD_target, OMPD_update, OMPD_target_update}, 149 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 150 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 151 {OMPD_for, OMPD_simd, OMPD_for_simd}, 152 {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 153 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 154 {OMPD_parallel, OMPD_loop, OMPD_parallel_loop}, 155 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 156 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 157 {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 158 {OMPD_target, OMPD_simd, OMPD_target_simd}, 159 {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop}, 160 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 161 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 162 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 163 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 164 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 165 {OMPD_teams_distribute_parallel, OMPD_for, 166 OMPD_teams_distribute_parallel_for}, 167 {OMPD_teams_distribute_parallel_for, OMPD_simd, 168 OMPD_teams_distribute_parallel_for_simd}, 169 {OMPD_teams, OMPD_loop, OMPD_teams_loop}, 170 {OMPD_target, OMPD_teams, OMPD_target_teams}, 171 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 172 {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop}, 173 {OMPD_target_teams_distribute, OMPD_parallel, 174 OMPD_target_teams_distribute_parallel}, 175 {OMPD_target_teams_distribute, OMPD_simd, 176 OMPD_target_teams_distribute_simd}, 177 {OMPD_target_teams_distribute_parallel, OMPD_for, 178 OMPD_target_teams_distribute_parallel_for}, 179 {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 180 OMPD_target_teams_distribute_parallel_for_simd}, 181 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, 182 {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop}, 183 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, 184 {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd}, 185 {OMPD_parallel, OMPD_master, OMPD_parallel_master}, 186 {OMPD_parallel, OMPD_masked, OMPD_parallel_masked}, 187 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, 188 {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop}, 189 {OMPD_parallel_master_taskloop, OMPD_simd, 190 OMPD_parallel_master_taskloop_simd}, 191 {OMPD_parallel_masked_taskloop, OMPD_simd, 192 OMPD_parallel_masked_taskloop_simd}}; 193 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 194 Token Tok = P.getCurToken(); 195 OpenMPDirectiveKindExWrapper DKind = 196 Tok.isAnnotation() 197 ? static_cast<unsigned>(OMPD_unknown) 198 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 199 if (DKind == OMPD_unknown) 200 return OMPD_unknown; 201 202 for (const auto &I : F) { 203 if (DKind != I[0]) 204 continue; 205 206 Tok = P.getPreprocessor().LookAhead(0); 207 OpenMPDirectiveKindExWrapper SDKind = 208 Tok.isAnnotation() 209 ? static_cast<unsigned>(OMPD_unknown) 210 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 211 if (SDKind == OMPD_unknown) 212 continue; 213 214 if (SDKind == I[1]) { 215 P.ConsumeToken(); 216 DKind = I[2]; 217 } 218 } 219 return unsigned(DKind) < llvm::omp::Directive_enumSize 220 ? static_cast<OpenMPDirectiveKind>(DKind) 221 : OMPD_unknown; 222 } 223 224 static DeclarationName parseOpenMPReductionId(Parser &P) { 225 Token Tok = P.getCurToken(); 226 Sema &Actions = P.getActions(); 227 OverloadedOperatorKind OOK = OO_None; 228 // Allow to use 'operator' keyword for C++ operators 229 bool WithOperator = false; 230 if (Tok.is(tok::kw_operator)) { 231 P.ConsumeToken(); 232 Tok = P.getCurToken(); 233 WithOperator = true; 234 } 235 switch (Tok.getKind()) { 236 case tok::plus: // '+' 237 OOK = OO_Plus; 238 break; 239 case tok::minus: // '-' 240 OOK = OO_Minus; 241 break; 242 case tok::star: // '*' 243 OOK = OO_Star; 244 break; 245 case tok::amp: // '&' 246 OOK = OO_Amp; 247 break; 248 case tok::pipe: // '|' 249 OOK = OO_Pipe; 250 break; 251 case tok::caret: // '^' 252 OOK = OO_Caret; 253 break; 254 case tok::ampamp: // '&&' 255 OOK = OO_AmpAmp; 256 break; 257 case tok::pipepipe: // '||' 258 OOK = OO_PipePipe; 259 break; 260 case tok::identifier: // identifier 261 if (!WithOperator) 262 break; 263 [[fallthrough]]; 264 default: 265 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 266 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 267 Parser::StopBeforeMatch); 268 return DeclarationName(); 269 } 270 P.ConsumeToken(); 271 auto &DeclNames = Actions.getASTContext().DeclarationNames; 272 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 273 : DeclNames.getCXXOperatorName(OOK); 274 } 275 276 /// Parse 'omp declare reduction' construct. 277 /// 278 /// declare-reduction-directive: 279 /// annot_pragma_openmp 'declare' 'reduction' 280 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 281 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 282 /// annot_pragma_openmp_end 283 /// <reduction_id> is either a base language identifier or one of the following 284 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 285 /// 286 Parser::DeclGroupPtrTy 287 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 288 // Parse '('. 289 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 290 if (T.expectAndConsume( 291 diag::err_expected_lparen_after, 292 getOpenMPDirectiveName(OMPD_declare_reduction).data())) { 293 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 294 return DeclGroupPtrTy(); 295 } 296 297 DeclarationName Name = parseOpenMPReductionId(*this); 298 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 299 return DeclGroupPtrTy(); 300 301 // Consume ':'. 302 bool IsCorrect = !ExpectAndConsume(tok::colon); 303 304 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 305 return DeclGroupPtrTy(); 306 307 IsCorrect = IsCorrect && !Name.isEmpty(); 308 309 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 310 Diag(Tok.getLocation(), diag::err_expected_type); 311 IsCorrect = false; 312 } 313 314 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 315 return DeclGroupPtrTy(); 316 317 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 318 // Parse list of types until ':' token. 319 do { 320 ColonProtectionRAIIObject ColonRAII(*this); 321 SourceRange Range; 322 TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS); 323 if (TR.isUsable()) { 324 QualType ReductionType = 325 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 326 if (!ReductionType.isNull()) { 327 ReductionTypes.push_back( 328 std::make_pair(ReductionType, Range.getBegin())); 329 } 330 } else { 331 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 332 StopBeforeMatch); 333 } 334 335 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 336 break; 337 338 // Consume ','. 339 if (ExpectAndConsume(tok::comma)) { 340 IsCorrect = false; 341 if (Tok.is(tok::annot_pragma_openmp_end)) { 342 Diag(Tok.getLocation(), diag::err_expected_type); 343 return DeclGroupPtrTy(); 344 } 345 } 346 } while (Tok.isNot(tok::annot_pragma_openmp_end)); 347 348 if (ReductionTypes.empty()) { 349 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 350 return DeclGroupPtrTy(); 351 } 352 353 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 354 return DeclGroupPtrTy(); 355 356 // Consume ':'. 357 if (ExpectAndConsume(tok::colon)) 358 IsCorrect = false; 359 360 if (Tok.is(tok::annot_pragma_openmp_end)) { 361 Diag(Tok.getLocation(), diag::err_expected_expression); 362 return DeclGroupPtrTy(); 363 } 364 365 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 366 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 367 368 // Parse <combiner> expression and then parse initializer if any for each 369 // correct type. 370 unsigned I = 0, E = ReductionTypes.size(); 371 for (Decl *D : DRD.get()) { 372 TentativeParsingAction TPA(*this); 373 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 374 Scope::CompoundStmtScope | 375 Scope::OpenMPDirectiveScope); 376 // Parse <combiner> expression. 377 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 378 ExprResult CombinerResult = Actions.ActOnFinishFullExpr( 379 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false); 380 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 381 382 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 383 Tok.isNot(tok::annot_pragma_openmp_end)) { 384 TPA.Commit(); 385 IsCorrect = false; 386 break; 387 } 388 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 389 ExprResult InitializerResult; 390 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 391 // Parse <initializer> expression. 392 if (Tok.is(tok::identifier) && 393 Tok.getIdentifierInfo()->isStr("initializer")) { 394 ConsumeToken(); 395 } else { 396 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 397 TPA.Commit(); 398 IsCorrect = false; 399 break; 400 } 401 // Parse '('. 402 BalancedDelimiterTracker T(*this, tok::l_paren, 403 tok::annot_pragma_openmp_end); 404 IsCorrect = 405 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 406 IsCorrect; 407 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 408 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 409 Scope::CompoundStmtScope | 410 Scope::OpenMPDirectiveScope); 411 // Parse expression. 412 VarDecl *OmpPrivParm = 413 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 414 D); 415 // Check if initializer is omp_priv <init_expr> or something else. 416 if (Tok.is(tok::identifier) && 417 Tok.getIdentifierInfo()->isStr("omp_priv")) { 418 ConsumeToken(); 419 ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 420 } else { 421 InitializerResult = Actions.ActOnFinishFullExpr( 422 ParseAssignmentExpression().get(), D->getLocation(), 423 /*DiscardedValue*/ false); 424 } 425 Actions.ActOnOpenMPDeclareReductionInitializerEnd( 426 D, InitializerResult.get(), OmpPrivParm); 427 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 428 Tok.isNot(tok::annot_pragma_openmp_end)) { 429 TPA.Commit(); 430 IsCorrect = false; 431 break; 432 } 433 IsCorrect = 434 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 435 } 436 } 437 438 ++I; 439 // Revert parsing if not the last type, otherwise accept it, we're done with 440 // parsing. 441 if (I != E) 442 TPA.Revert(); 443 else 444 TPA.Commit(); 445 } 446 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 447 IsCorrect); 448 } 449 450 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 451 // Parse declarator '=' initializer. 452 // If a '==' or '+=' is found, suggest a fixit to '='. 453 if (isTokenEqualOrEqualTypo()) { 454 ConsumeToken(); 455 456 if (Tok.is(tok::code_completion)) { 457 cutOffParsing(); 458 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 459 Actions.FinalizeDeclaration(OmpPrivParm); 460 return; 461 } 462 463 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm); 464 ExprResult Init = ParseInitializer(); 465 466 if (Init.isInvalid()) { 467 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 468 Actions.ActOnInitializerError(OmpPrivParm); 469 } else { 470 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 471 /*DirectInit=*/false); 472 } 473 } else if (Tok.is(tok::l_paren)) { 474 // Parse C++ direct initializer: '(' expression-list ')' 475 BalancedDelimiterTracker T(*this, tok::l_paren); 476 T.consumeOpen(); 477 478 ExprVector Exprs; 479 480 SourceLocation LParLoc = T.getOpenLocation(); 481 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { 482 QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 483 OmpPrivParm->getType()->getCanonicalTypeInternal(), 484 OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false); 485 CalledSignatureHelp = true; 486 return PreferredType; 487 }; 488 if (ParseExpressionList(Exprs, [&] { 489 PreferredType.enterFunctionArgument(Tok.getLocation(), 490 RunSignatureHelp); 491 })) { 492 if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 493 RunSignatureHelp(); 494 Actions.ActOnInitializerError(OmpPrivParm); 495 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 496 } else { 497 // Match the ')'. 498 SourceLocation RLoc = Tok.getLocation(); 499 if (!T.consumeClose()) 500 RLoc = T.getCloseLocation(); 501 502 ExprResult Initializer = 503 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); 504 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), 505 /*DirectInit=*/true); 506 } 507 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 508 // Parse C++0x braced-init-list. 509 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 510 511 ExprResult Init(ParseBraceInitializer()); 512 513 if (Init.isInvalid()) { 514 Actions.ActOnInitializerError(OmpPrivParm); 515 } else { 516 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 517 /*DirectInit=*/true); 518 } 519 } else { 520 Actions.ActOnUninitializedDecl(OmpPrivParm); 521 } 522 } 523 524 /// Parses 'omp declare mapper' directive. 525 /// 526 /// declare-mapper-directive: 527 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':'] 528 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 529 /// annot_pragma_openmp_end 530 /// <mapper-identifier> and <var> are base language identifiers. 531 /// 532 Parser::DeclGroupPtrTy 533 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { 534 bool IsCorrect = true; 535 // Parse '(' 536 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 537 if (T.expectAndConsume(diag::err_expected_lparen_after, 538 getOpenMPDirectiveName(OMPD_declare_mapper).data())) { 539 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 540 return DeclGroupPtrTy(); 541 } 542 543 // Parse <mapper-identifier> 544 auto &DeclNames = Actions.getASTContext().DeclarationNames; 545 DeclarationName MapperId; 546 if (PP.LookAhead(0).is(tok::colon)) { 547 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 548 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 549 IsCorrect = false; 550 } else { 551 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo()); 552 } 553 ConsumeToken(); 554 // Consume ':'. 555 ExpectAndConsume(tok::colon); 556 } else { 557 // If no mapper identifier is provided, its name is "default" by default 558 MapperId = 559 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default")); 560 } 561 562 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 563 return DeclGroupPtrTy(); 564 565 // Parse <type> <var> 566 DeclarationName VName; 567 QualType MapperType; 568 SourceRange Range; 569 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS); 570 if (ParsedType.isUsable()) 571 MapperType = 572 Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType); 573 if (MapperType.isNull()) 574 IsCorrect = false; 575 if (!IsCorrect) { 576 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 577 return DeclGroupPtrTy(); 578 } 579 580 // Consume ')'. 581 IsCorrect &= !T.consumeClose(); 582 if (!IsCorrect) { 583 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 584 return DeclGroupPtrTy(); 585 } 586 587 // Enter scope. 588 DeclarationNameInfo DirName; 589 SourceLocation Loc = Tok.getLocation(); 590 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 591 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 592 ParseScope OMPDirectiveScope(this, ScopeFlags); 593 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc); 594 595 // Add the mapper variable declaration. 596 ExprResult MapperVarRef = Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl( 597 getCurScope(), MapperType, Range.getBegin(), VName); 598 599 // Parse map clauses. 600 SmallVector<OMPClause *, 6> Clauses; 601 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 602 OpenMPClauseKind CKind = Tok.isAnnotation() 603 ? OMPC_unknown 604 : getOpenMPClauseKind(PP.getSpelling(Tok)); 605 Actions.StartOpenMPClause(CKind); 606 OMPClause *Clause = 607 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty()); 608 if (Clause) 609 Clauses.push_back(Clause); 610 else 611 IsCorrect = false; 612 // Skip ',' if any. 613 if (Tok.is(tok::comma)) 614 ConsumeToken(); 615 Actions.EndOpenMPClause(); 616 } 617 if (Clauses.empty()) { 618 Diag(Tok, diag::err_omp_expected_clause) 619 << getOpenMPDirectiveName(OMPD_declare_mapper); 620 IsCorrect = false; 621 } 622 623 // Exit scope. 624 Actions.EndOpenMPDSABlock(nullptr); 625 OMPDirectiveScope.Exit(); 626 DeclGroupPtrTy DG = Actions.ActOnOpenMPDeclareMapperDirective( 627 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType, 628 Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses); 629 if (!IsCorrect) 630 return DeclGroupPtrTy(); 631 632 return DG; 633 } 634 635 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, 636 DeclarationName &Name, 637 AccessSpecifier AS) { 638 // Parse the common declaration-specifiers piece. 639 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier; 640 DeclSpec DS(AttrFactory); 641 ParseSpecifierQualifierList(DS, AS, DSC); 642 643 // Parse the declarator. 644 DeclaratorContext Context = DeclaratorContext::Prototype; 645 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context); 646 ParseDeclarator(DeclaratorInfo); 647 Range = DeclaratorInfo.getSourceRange(); 648 if (DeclaratorInfo.getIdentifier() == nullptr) { 649 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator); 650 return true; 651 } 652 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName(); 653 654 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo); 655 } 656 657 namespace { 658 /// RAII that recreates function context for correct parsing of clauses of 659 /// 'declare simd' construct. 660 /// OpenMP, 2.8.2 declare simd Construct 661 /// The expressions appearing in the clauses of this directive are evaluated in 662 /// the scope of the arguments of the function declaration or definition. 663 class FNContextRAII final { 664 Parser &P; 665 Sema::CXXThisScopeRAII *ThisScope; 666 Parser::MultiParseScope Scopes; 667 bool HasFunScope = false; 668 FNContextRAII() = delete; 669 FNContextRAII(const FNContextRAII &) = delete; 670 FNContextRAII &operator=(const FNContextRAII &) = delete; 671 672 public: 673 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) { 674 Decl *D = *Ptr.get().begin(); 675 NamedDecl *ND = dyn_cast<NamedDecl>(D); 676 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 677 Sema &Actions = P.getActions(); 678 679 // Allow 'this' within late-parsed attributes. 680 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), 681 ND && ND->isCXXInstanceMember()); 682 683 // If the Decl is templatized, add template parameters to scope. 684 // FIXME: Track CurTemplateDepth? 685 P.ReenterTemplateScopes(Scopes, D); 686 687 // If the Decl is on a function, add function parameters to the scope. 688 if (D->isFunctionOrFunctionTemplate()) { 689 HasFunScope = true; 690 Scopes.Enter(Scope::FnScope | Scope::DeclScope | 691 Scope::CompoundStmtScope); 692 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 693 } 694 } 695 ~FNContextRAII() { 696 if (HasFunScope) 697 P.getActions().ActOnExitFunctionContext(); 698 delete ThisScope; 699 } 700 }; 701 } // namespace 702 703 /// Parses clauses for 'declare simd' directive. 704 /// clause: 705 /// 'inbranch' | 'notinbranch' 706 /// 'simdlen' '(' <expr> ')' 707 /// { 'uniform' '(' <argument_list> ')' } 708 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 709 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 710 static bool parseDeclareSimdClauses( 711 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 712 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 713 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 714 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 715 SourceRange BSRange; 716 const Token &Tok = P.getCurToken(); 717 bool IsError = false; 718 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 719 if (Tok.isNot(tok::identifier)) 720 break; 721 OMPDeclareSimdDeclAttr::BranchStateTy Out; 722 IdentifierInfo *II = Tok.getIdentifierInfo(); 723 StringRef ClauseName = II->getName(); 724 // Parse 'inranch|notinbranch' clauses. 725 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 726 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 727 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 728 << ClauseName 729 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 730 IsError = true; 731 } 732 BS = Out; 733 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 734 P.ConsumeToken(); 735 } else if (ClauseName.equals("simdlen")) { 736 if (SimdLen.isUsable()) { 737 P.Diag(Tok, diag::err_omp_more_one_clause) 738 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 739 IsError = true; 740 } 741 P.ConsumeToken(); 742 SourceLocation RLoc; 743 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 744 if (SimdLen.isInvalid()) 745 IsError = true; 746 } else { 747 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 748 if (CKind == OMPC_uniform || CKind == OMPC_aligned || 749 CKind == OMPC_linear) { 750 Sema::OpenMPVarListDataTy Data; 751 SmallVectorImpl<Expr *> *Vars = &Uniforms; 752 if (CKind == OMPC_aligned) { 753 Vars = &Aligneds; 754 } else if (CKind == OMPC_linear) { 755 Data.ExtraModifier = OMPC_LINEAR_val; 756 Vars = &Linears; 757 } 758 759 P.ConsumeToken(); 760 if (P.ParseOpenMPVarList(OMPD_declare_simd, 761 getOpenMPClauseKind(ClauseName), *Vars, Data)) 762 IsError = true; 763 if (CKind == OMPC_aligned) { 764 Alignments.append(Aligneds.size() - Alignments.size(), 765 Data.DepModOrTailExpr); 766 } else if (CKind == OMPC_linear) { 767 assert(0 <= Data.ExtraModifier && 768 Data.ExtraModifier <= OMPC_LINEAR_unknown && 769 "Unexpected linear modifier."); 770 if (P.getActions().CheckOpenMPLinearModifier( 771 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier), 772 Data.ExtraModifierLoc)) 773 Data.ExtraModifier = OMPC_LINEAR_val; 774 LinModifiers.append(Linears.size() - LinModifiers.size(), 775 Data.ExtraModifier); 776 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr); 777 } 778 } else 779 // TODO: add parsing of other clauses. 780 break; 781 } 782 // Skip ',' if any. 783 if (Tok.is(tok::comma)) 784 P.ConsumeToken(); 785 } 786 return IsError; 787 } 788 789 /// Parse clauses for '#pragma omp declare simd'. 790 Parser::DeclGroupPtrTy 791 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 792 CachedTokens &Toks, SourceLocation Loc) { 793 PP.EnterToken(Tok, /*IsReinject*/ true); 794 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 795 /*IsReinject*/ true); 796 // Consume the previously pushed token. 797 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 798 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 799 800 FNContextRAII FnContext(*this, Ptr); 801 OMPDeclareSimdDeclAttr::BranchStateTy BS = 802 OMPDeclareSimdDeclAttr::BS_Undefined; 803 ExprResult Simdlen; 804 SmallVector<Expr *, 4> Uniforms; 805 SmallVector<Expr *, 4> Aligneds; 806 SmallVector<Expr *, 4> Alignments; 807 SmallVector<Expr *, 4> Linears; 808 SmallVector<unsigned, 4> LinModifiers; 809 SmallVector<Expr *, 4> Steps; 810 bool IsError = 811 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 812 Alignments, Linears, LinModifiers, Steps); 813 skipUntilPragmaOpenMPEnd(OMPD_declare_simd); 814 // Skip the last annot_pragma_openmp_end. 815 SourceLocation EndLoc = ConsumeAnnotationToken(); 816 if (IsError) 817 return Ptr; 818 return Actions.ActOnOpenMPDeclareSimdDirective( 819 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 820 LinModifiers, Steps, SourceRange(Loc, EndLoc)); 821 } 822 823 namespace { 824 /// Constant used in the diagnostics to distinguish the levels in an OpenMP 825 /// contexts: selector-set={selector(trait, ...), ...}, .... 826 enum OMPContextLvl { 827 CONTEXT_SELECTOR_SET_LVL = 0, 828 CONTEXT_SELECTOR_LVL = 1, 829 CONTEXT_TRAIT_LVL = 2, 830 }; 831 832 static StringRef stringLiteralParser(Parser &P) { 833 ExprResult Res = P.ParseStringLiteralExpression(true); 834 return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : ""; 835 } 836 837 static StringRef getNameFromIdOrString(Parser &P, Token &Tok, 838 OMPContextLvl Lvl) { 839 if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) { 840 llvm::SmallString<16> Buffer; 841 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer); 842 (void)P.ConsumeToken(); 843 return Name; 844 } 845 846 if (tok::isStringLiteral(Tok.getKind())) 847 return stringLiteralParser(P); 848 849 P.Diag(Tok.getLocation(), 850 diag::warn_omp_declare_variant_string_literal_or_identifier) 851 << Lvl; 852 return ""; 853 } 854 855 static bool checkForDuplicates(Parser &P, StringRef Name, 856 SourceLocation NameLoc, 857 llvm::StringMap<SourceLocation> &Seen, 858 OMPContextLvl Lvl) { 859 auto Res = Seen.try_emplace(Name, NameLoc); 860 if (Res.second) 861 return false; 862 863 // Each trait-set-selector-name, trait-selector-name and trait-name can 864 // only be specified once. 865 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use) 866 << Lvl << Name; 867 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) 868 << Lvl << Name; 869 return true; 870 } 871 } // namespace 872 873 void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty, 874 llvm::omp::TraitSet Set, 875 llvm::omp::TraitSelector Selector, 876 llvm::StringMap<SourceLocation> &Seen) { 877 TIProperty.Kind = TraitProperty::invalid; 878 879 SourceLocation NameLoc = Tok.getLocation(); 880 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL); 881 if (Name.empty()) { 882 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 883 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector); 884 return; 885 } 886 887 TIProperty.RawString = Name; 888 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name); 889 if (TIProperty.Kind != TraitProperty::invalid) { 890 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL)) 891 TIProperty.Kind = TraitProperty::invalid; 892 return; 893 } 894 895 // It follows diagnosis and helping notes. 896 // FIXME: We should move the diagnosis string generation into libFrontend. 897 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property) 898 << Name << getOpenMPContextTraitSelectorName(Selector) 899 << getOpenMPContextTraitSetName(Set); 900 901 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 902 if (SetForName != TraitSet::invalid) { 903 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 904 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL; 905 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 906 << Name << "<selector-name>" 907 << "(<property-name>)"; 908 return; 909 } 910 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 911 if (SelectorForName != TraitSelector::invalid) { 912 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 913 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL; 914 bool AllowsTraitScore = false; 915 bool RequiresProperty = false; 916 isValidTraitSelectorForTraitSet( 917 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 918 AllowsTraitScore, RequiresProperty); 919 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 920 << getOpenMPContextTraitSetName( 921 getOpenMPContextTraitSetForSelector(SelectorForName)) 922 << Name << (RequiresProperty ? "(<property-name>)" : ""); 923 return; 924 } 925 for (const auto &PotentialSet : 926 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 927 TraitSet::device}) { 928 TraitProperty PropertyForName = 929 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name); 930 if (PropertyForName == TraitProperty::invalid) 931 continue; 932 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 933 << getOpenMPContextTraitSetName( 934 getOpenMPContextTraitSetForProperty(PropertyForName)) 935 << getOpenMPContextTraitSelectorName( 936 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 937 << ("(" + Name + ")").str(); 938 return; 939 } 940 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 941 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector); 942 } 943 944 static bool checkExtensionProperty(Parser &P, SourceLocation Loc, 945 OMPTraitProperty &TIProperty, 946 OMPTraitSelector &TISelector, 947 llvm::StringMap<SourceLocation> &Seen) { 948 assert(TISelector.Kind == 949 llvm::omp::TraitSelector::implementation_extension && 950 "Only for extension properties, e.g., " 951 "`implementation={extension(PROPERTY)}`"); 952 if (TIProperty.Kind == TraitProperty::invalid) 953 return false; 954 955 if (TIProperty.Kind == 956 TraitProperty::implementation_extension_disable_implicit_base) 957 return true; 958 959 if (TIProperty.Kind == 960 TraitProperty::implementation_extension_allow_templates) 961 return true; 962 963 if (TIProperty.Kind == 964 TraitProperty::implementation_extension_bind_to_declaration) 965 return true; 966 967 auto IsMatchExtension = [](OMPTraitProperty &TP) { 968 return (TP.Kind == 969 llvm::omp::TraitProperty::implementation_extension_match_all || 970 TP.Kind == 971 llvm::omp::TraitProperty::implementation_extension_match_any || 972 TP.Kind == 973 llvm::omp::TraitProperty::implementation_extension_match_none); 974 }; 975 976 if (IsMatchExtension(TIProperty)) { 977 for (OMPTraitProperty &SeenProp : TISelector.Properties) 978 if (IsMatchExtension(SeenProp)) { 979 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension); 980 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName( 981 SeenProp.Kind, SeenProp.RawString); 982 SourceLocation SeenLoc = Seen[SeenName]; 983 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here) 984 << CONTEXT_TRAIT_LVL << SeenName; 985 return false; 986 } 987 return true; 988 } 989 990 llvm_unreachable("Unknown extension property!"); 991 } 992 993 void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector, 994 llvm::omp::TraitSet Set, 995 llvm::StringMap<SourceLocation> &Seen) { 996 assert(TISelector.Kind != TraitSelector::user_condition && 997 "User conditions are special properties not handled here!"); 998 999 SourceLocation PropertyLoc = Tok.getLocation(); 1000 OMPTraitProperty TIProperty; 1001 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen); 1002 1003 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension) 1004 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty, 1005 TISelector, Seen)) 1006 TIProperty.Kind = TraitProperty::invalid; 1007 1008 // If we have an invalid property here we already issued a warning. 1009 if (TIProperty.Kind == TraitProperty::invalid) { 1010 if (PropertyLoc != Tok.getLocation()) 1011 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1012 << CONTEXT_TRAIT_LVL; 1013 return; 1014 } 1015 1016 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind, 1017 TISelector.Kind, Set)) { 1018 1019 // If we make it here the property, selector, set, score, condition, ... are 1020 // all valid (or have been corrected). Thus we can record the property. 1021 TISelector.Properties.push_back(TIProperty); 1022 return; 1023 } 1024 1025 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector) 1026 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 1027 TIProperty.RawString) 1028 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1029 << getOpenMPContextTraitSetName(Set); 1030 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property) 1031 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 1032 TIProperty.RawString) 1033 << getOpenMPContextTraitSelectorName( 1034 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind)) 1035 << getOpenMPContextTraitSetName( 1036 getOpenMPContextTraitSetForProperty(TIProperty.Kind)); 1037 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1038 << CONTEXT_TRAIT_LVL; 1039 } 1040 1041 void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector, 1042 llvm::omp::TraitSet Set, 1043 llvm::StringMap<SourceLocation> &Seen) { 1044 TISelector.Kind = TraitSelector::invalid; 1045 1046 SourceLocation NameLoc = Tok.getLocation(); 1047 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL); 1048 if (Name.empty()) { 1049 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1050 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1051 return; 1052 } 1053 1054 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name); 1055 if (TISelector.Kind != TraitSelector::invalid) { 1056 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL)) 1057 TISelector.Kind = TraitSelector::invalid; 1058 return; 1059 } 1060 1061 // It follows diagnosis and helping notes. 1062 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector) 1063 << Name << getOpenMPContextTraitSetName(Set); 1064 1065 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 1066 if (SetForName != TraitSet::invalid) { 1067 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1068 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL; 1069 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1070 << Name << "<selector-name>" 1071 << "<property-name>"; 1072 return; 1073 } 1074 for (const auto &PotentialSet : 1075 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1076 TraitSet::device}) { 1077 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1078 PotentialSet, TraitSelector::invalid, Name); 1079 if (PropertyForName == TraitProperty::invalid) 1080 continue; 1081 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1082 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL; 1083 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1084 << getOpenMPContextTraitSetName( 1085 getOpenMPContextTraitSetForProperty(PropertyForName)) 1086 << getOpenMPContextTraitSelectorName( 1087 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1088 << ("(" + Name + ")").str(); 1089 return; 1090 } 1091 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1092 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1093 } 1094 1095 /// Parse optional 'score' '(' <expr> ')' ':'. 1096 static ExprResult parseContextScore(Parser &P) { 1097 ExprResult ScoreExpr; 1098 llvm::SmallString<16> Buffer; 1099 StringRef SelectorName = 1100 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 1101 if (!SelectorName.equals("score")) 1102 return ScoreExpr; 1103 (void)P.ConsumeToken(); 1104 SourceLocation RLoc; 1105 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); 1106 // Parse ':' 1107 if (P.getCurToken().is(tok::colon)) 1108 (void)P.ConsumeAnyToken(); 1109 else 1110 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected) 1111 << "':'" 1112 << "score expression"; 1113 return ScoreExpr; 1114 } 1115 1116 /// Parses an OpenMP context selector. 1117 /// 1118 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')'] 1119 void Parser::parseOMPContextSelector( 1120 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1121 llvm::StringMap<SourceLocation> &SeenSelectors) { 1122 unsigned short OuterPC = ParenCount; 1123 1124 // If anything went wrong we issue an error or warning and then skip the rest 1125 // of the selector. However, commas are ambiguous so we look for the nesting 1126 // of parentheses here as well. 1127 auto FinishSelector = [OuterPC, this]() -> void { 1128 bool Done = false; 1129 while (!Done) { 1130 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma, 1131 tok::annot_pragma_openmp_end}, 1132 StopBeforeMatch)) 1133 ; 1134 if (Tok.is(tok::r_paren) && OuterPC > ParenCount) 1135 (void)ConsumeParen(); 1136 if (OuterPC <= ParenCount) { 1137 Done = true; 1138 break; 1139 } 1140 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) { 1141 Done = true; 1142 break; 1143 } 1144 (void)ConsumeAnyToken(); 1145 } 1146 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1147 << CONTEXT_SELECTOR_LVL; 1148 }; 1149 1150 SourceLocation SelectorLoc = Tok.getLocation(); 1151 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors); 1152 if (TISelector.Kind == TraitSelector::invalid) 1153 return FinishSelector(); 1154 1155 bool AllowsTraitScore = false; 1156 bool RequiresProperty = false; 1157 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore, 1158 RequiresProperty)) { 1159 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set) 1160 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1161 << getOpenMPContextTraitSetName(Set); 1162 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector) 1163 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1164 << getOpenMPContextTraitSetName( 1165 getOpenMPContextTraitSetForSelector(TISelector.Kind)) 1166 << RequiresProperty; 1167 return FinishSelector(); 1168 } 1169 1170 if (!RequiresProperty) { 1171 TISelector.Properties.push_back( 1172 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind), 1173 getOpenMPContextTraitSelectorName(TISelector.Kind)}); 1174 return; 1175 } 1176 1177 if (!Tok.is(tok::l_paren)) { 1178 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties) 1179 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1180 << getOpenMPContextTraitSetName(Set); 1181 return FinishSelector(); 1182 } 1183 1184 if (TISelector.Kind == TraitSelector::user_condition) { 1185 SourceLocation RLoc; 1186 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc); 1187 if (!Condition.isUsable()) 1188 return FinishSelector(); 1189 TISelector.ScoreOrCondition = Condition.get(); 1190 TISelector.Properties.push_back( 1191 {TraitProperty::user_condition_unknown, "<condition>"}); 1192 return; 1193 } 1194 1195 BalancedDelimiterTracker BDT(*this, tok::l_paren, 1196 tok::annot_pragma_openmp_end); 1197 // Parse '('. 1198 (void)BDT.consumeOpen(); 1199 1200 SourceLocation ScoreLoc = Tok.getLocation(); 1201 ExprResult Score = parseContextScore(*this); 1202 1203 if (!AllowsTraitScore && !Score.isUnset()) { 1204 if (Score.isUsable()) { 1205 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1206 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1207 << getOpenMPContextTraitSetName(Set) << Score.get(); 1208 } else { 1209 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1210 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1211 << getOpenMPContextTraitSetName(Set) << "<invalid>"; 1212 } 1213 Score = ExprResult(); 1214 } 1215 1216 if (Score.isUsable()) 1217 TISelector.ScoreOrCondition = Score.get(); 1218 1219 llvm::StringMap<SourceLocation> SeenProperties; 1220 do { 1221 parseOMPContextProperty(TISelector, Set, SeenProperties); 1222 } while (TryConsumeToken(tok::comma)); 1223 1224 // Parse ')'. 1225 BDT.consumeClose(); 1226 } 1227 1228 void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet, 1229 llvm::StringMap<SourceLocation> &Seen) { 1230 TISet.Kind = TraitSet::invalid; 1231 1232 SourceLocation NameLoc = Tok.getLocation(); 1233 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL); 1234 if (Name.empty()) { 1235 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1236 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1237 return; 1238 } 1239 1240 TISet.Kind = getOpenMPContextTraitSetKind(Name); 1241 if (TISet.Kind != TraitSet::invalid) { 1242 if (checkForDuplicates(*this, Name, NameLoc, Seen, 1243 CONTEXT_SELECTOR_SET_LVL)) 1244 TISet.Kind = TraitSet::invalid; 1245 return; 1246 } 1247 1248 // It follows diagnosis and helping notes. 1249 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name; 1250 1251 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 1252 if (SelectorForName != TraitSelector::invalid) { 1253 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1254 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL; 1255 bool AllowsTraitScore = false; 1256 bool RequiresProperty = false; 1257 isValidTraitSelectorForTraitSet( 1258 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 1259 AllowsTraitScore, RequiresProperty); 1260 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1261 << getOpenMPContextTraitSetName( 1262 getOpenMPContextTraitSetForSelector(SelectorForName)) 1263 << Name << (RequiresProperty ? "(<property-name>)" : ""); 1264 return; 1265 } 1266 for (const auto &PotentialSet : 1267 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1268 TraitSet::device}) { 1269 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1270 PotentialSet, TraitSelector::invalid, Name); 1271 if (PropertyForName == TraitProperty::invalid) 1272 continue; 1273 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1274 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL; 1275 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1276 << getOpenMPContextTraitSetName( 1277 getOpenMPContextTraitSetForProperty(PropertyForName)) 1278 << getOpenMPContextTraitSelectorName( 1279 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1280 << ("(" + Name + ")").str(); 1281 return; 1282 } 1283 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1284 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1285 } 1286 1287 /// Parses an OpenMP context selector set. 1288 /// 1289 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}' 1290 void Parser::parseOMPContextSelectorSet( 1291 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) { 1292 auto OuterBC = BraceCount; 1293 1294 // If anything went wrong we issue an error or warning and then skip the rest 1295 // of the set. However, commas are ambiguous so we look for the nesting 1296 // of braces here as well. 1297 auto FinishSelectorSet = [this, OuterBC]() -> void { 1298 bool Done = false; 1299 while (!Done) { 1300 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren, 1301 tok::annot_pragma_openmp_end}, 1302 StopBeforeMatch)) 1303 ; 1304 if (Tok.is(tok::r_brace) && OuterBC > BraceCount) 1305 (void)ConsumeBrace(); 1306 if (OuterBC <= BraceCount) { 1307 Done = true; 1308 break; 1309 } 1310 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) { 1311 Done = true; 1312 break; 1313 } 1314 (void)ConsumeAnyToken(); 1315 } 1316 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1317 << CONTEXT_SELECTOR_SET_LVL; 1318 }; 1319 1320 parseOMPTraitSetKind(TISet, SeenSets); 1321 if (TISet.Kind == TraitSet::invalid) 1322 return FinishSelectorSet(); 1323 1324 // Parse '='. 1325 if (!TryConsumeToken(tok::equal)) 1326 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1327 << "=" 1328 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) + 1329 "\"") 1330 .str(); 1331 1332 // Parse '{'. 1333 if (Tok.is(tok::l_brace)) { 1334 (void)ConsumeBrace(); 1335 } else { 1336 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1337 << "{" 1338 << ("'=' that follows the context set name \"" + 1339 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1340 .str(); 1341 } 1342 1343 llvm::StringMap<SourceLocation> SeenSelectors; 1344 do { 1345 OMPTraitSelector TISelector; 1346 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors); 1347 if (TISelector.Kind != TraitSelector::invalid && 1348 !TISelector.Properties.empty()) 1349 TISet.Selectors.push_back(TISelector); 1350 } while (TryConsumeToken(tok::comma)); 1351 1352 // Parse '}'. 1353 if (Tok.is(tok::r_brace)) { 1354 (void)ConsumeBrace(); 1355 } else { 1356 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1357 << "}" 1358 << ("context selectors for the context set \"" + 1359 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1360 .str(); 1361 } 1362 } 1363 1364 /// Parse OpenMP context selectors: 1365 /// 1366 /// <trait-set-selector> [, <trait-set-selector>]* 1367 bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) { 1368 llvm::StringMap<SourceLocation> SeenSets; 1369 do { 1370 OMPTraitSet TISet; 1371 parseOMPContextSelectorSet(TISet, SeenSets); 1372 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty()) 1373 TI.Sets.push_back(TISet); 1374 } while (TryConsumeToken(tok::comma)); 1375 1376 return false; 1377 } 1378 1379 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. 1380 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, 1381 CachedTokens &Toks, 1382 SourceLocation Loc) { 1383 PP.EnterToken(Tok, /*IsReinject*/ true); 1384 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1385 /*IsReinject*/ true); 1386 // Consume the previously pushed token. 1387 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1388 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1389 1390 FNContextRAII FnContext(*this, Ptr); 1391 // Parse function declaration id. 1392 SourceLocation RLoc; 1393 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs 1394 // instead of MemberExprs. 1395 ExprResult AssociatedFunction; 1396 { 1397 // Do not mark function as is used to prevent its emission if this is the 1398 // only place where it is used. 1399 EnterExpressionEvaluationContext Unevaluated( 1400 Actions, Sema::ExpressionEvaluationContext::Unevaluated); 1401 AssociatedFunction = ParseOpenMPParensExpr( 1402 getOpenMPDirectiveName(OMPD_declare_variant), RLoc, 1403 /*IsAddressOfOperand=*/true); 1404 } 1405 if (!AssociatedFunction.isUsable()) { 1406 if (!Tok.is(tok::annot_pragma_openmp_end)) 1407 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1408 ; 1409 // Skip the last annot_pragma_openmp_end. 1410 (void)ConsumeAnnotationToken(); 1411 return; 1412 } 1413 1414 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope(); 1415 ASTContext &ASTCtx = Actions.getASTContext(); 1416 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); 1417 SmallVector<Expr *, 6> AdjustNothing; 1418 SmallVector<Expr *, 6> AdjustNeedDevicePtr; 1419 SmallVector<OMPInteropInfo, 3> AppendArgs; 1420 SourceLocation AdjustArgsLoc, AppendArgsLoc; 1421 1422 // At least one clause is required. 1423 if (Tok.is(tok::annot_pragma_openmp_end)) { 1424 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1425 << (getLangOpts().OpenMP < 51 ? 0 : 1); 1426 } 1427 1428 bool IsError = false; 1429 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1430 OpenMPClauseKind CKind = Tok.isAnnotation() 1431 ? OMPC_unknown 1432 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1433 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind, 1434 getLangOpts().OpenMP)) { 1435 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1436 << (getLangOpts().OpenMP < 51 ? 0 : 1); 1437 IsError = true; 1438 } 1439 if (!IsError) { 1440 switch (CKind) { 1441 case OMPC_match: 1442 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI); 1443 break; 1444 case OMPC_adjust_args: { 1445 AdjustArgsLoc = Tok.getLocation(); 1446 ConsumeToken(); 1447 Sema::OpenMPVarListDataTy Data; 1448 SmallVector<Expr *> Vars; 1449 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args, 1450 Vars, Data); 1451 if (!IsError) 1452 llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing 1453 ? AdjustNothing 1454 : AdjustNeedDevicePtr, 1455 Vars); 1456 break; 1457 } 1458 case OMPC_append_args: 1459 if (!AppendArgs.empty()) { 1460 Diag(AppendArgsLoc, diag::err_omp_more_one_clause) 1461 << getOpenMPDirectiveName(OMPD_declare_variant) 1462 << getOpenMPClauseName(CKind) << 0; 1463 IsError = true; 1464 } 1465 if (!IsError) { 1466 AppendArgsLoc = Tok.getLocation(); 1467 ConsumeToken(); 1468 IsError = parseOpenMPAppendArgs(AppendArgs); 1469 } 1470 break; 1471 default: 1472 llvm_unreachable("Unexpected clause for declare variant."); 1473 } 1474 } 1475 if (IsError) { 1476 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1477 ; 1478 // Skip the last annot_pragma_openmp_end. 1479 (void)ConsumeAnnotationToken(); 1480 return; 1481 } 1482 // Skip ',' if any. 1483 if (Tok.is(tok::comma)) 1484 ConsumeToken(); 1485 } 1486 1487 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = 1488 Actions.checkOpenMPDeclareVariantFunction( 1489 Ptr, AssociatedFunction.get(), TI, AppendArgs.size(), 1490 SourceRange(Loc, Tok.getLocation())); 1491 1492 if (DeclVarData && !TI.Sets.empty()) 1493 Actions.ActOnOpenMPDeclareVariantDirective( 1494 DeclVarData->first, DeclVarData->second, TI, AdjustNothing, 1495 AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc, 1496 SourceRange(Loc, Tok.getLocation())); 1497 1498 // Skip the last annot_pragma_openmp_end. 1499 (void)ConsumeAnnotationToken(); 1500 } 1501 1502 bool Parser::parseOpenMPAppendArgs( 1503 SmallVectorImpl<OMPInteropInfo> &InteropInfos) { 1504 bool HasError = false; 1505 // Parse '('. 1506 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1507 if (T.expectAndConsume(diag::err_expected_lparen_after, 1508 getOpenMPClauseName(OMPC_append_args).data())) 1509 return true; 1510 1511 // Parse the list of append-ops, each is; 1512 // interop(interop-type[,interop-type]...) 1513 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) { 1514 ConsumeToken(); 1515 BalancedDelimiterTracker IT(*this, tok::l_paren, 1516 tok::annot_pragma_openmp_end); 1517 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop")) 1518 return true; 1519 1520 OMPInteropInfo InteropInfo; 1521 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args)) 1522 HasError = true; 1523 else 1524 InteropInfos.push_back(InteropInfo); 1525 1526 IT.consumeClose(); 1527 if (Tok.is(tok::comma)) 1528 ConsumeToken(); 1529 } 1530 if (!HasError && InteropInfos.empty()) { 1531 HasError = true; 1532 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op); 1533 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1534 StopBeforeMatch); 1535 } 1536 HasError = T.consumeClose() || HasError; 1537 return HasError; 1538 } 1539 1540 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, 1541 OMPTraitInfo &TI, 1542 OMPTraitInfo *ParentTI) { 1543 // Parse 'match'. 1544 OpenMPClauseKind CKind = Tok.isAnnotation() 1545 ? OMPC_unknown 1546 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1547 if (CKind != OMPC_match) { 1548 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1549 << (getLangOpts().OpenMP < 51 ? 0 : 1); 1550 return true; 1551 } 1552 (void)ConsumeToken(); 1553 // Parse '('. 1554 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1555 if (T.expectAndConsume(diag::err_expected_lparen_after, 1556 getOpenMPClauseName(OMPC_match).data())) 1557 return true; 1558 1559 // Parse inner context selectors. 1560 parseOMPContextSelectors(Loc, TI); 1561 1562 // Parse ')' 1563 (void)T.consumeClose(); 1564 1565 if (!ParentTI) 1566 return false; 1567 1568 // Merge the parent/outer trait info into the one we just parsed and diagnose 1569 // problems. 1570 // TODO: Keep some source location in the TI to provide better diagnostics. 1571 // TODO: Perform some kind of equivalence check on the condition and score 1572 // expressions. 1573 for (const OMPTraitSet &ParentSet : ParentTI->Sets) { 1574 bool MergedSet = false; 1575 for (OMPTraitSet &Set : TI.Sets) { 1576 if (Set.Kind != ParentSet.Kind) 1577 continue; 1578 MergedSet = true; 1579 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) { 1580 bool MergedSelector = false; 1581 for (OMPTraitSelector &Selector : Set.Selectors) { 1582 if (Selector.Kind != ParentSelector.Kind) 1583 continue; 1584 MergedSelector = true; 1585 for (const OMPTraitProperty &ParentProperty : 1586 ParentSelector.Properties) { 1587 bool MergedProperty = false; 1588 for (OMPTraitProperty &Property : Selector.Properties) { 1589 // Ignore "equivalent" properties. 1590 if (Property.Kind != ParentProperty.Kind) 1591 continue; 1592 1593 // If the kind is the same but the raw string not, we don't want 1594 // to skip out on the property. 1595 MergedProperty |= Property.RawString == ParentProperty.RawString; 1596 1597 if (Property.RawString == ParentProperty.RawString && 1598 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition) 1599 continue; 1600 1601 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) { 1602 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition); 1603 } else if (Selector.ScoreOrCondition != 1604 ParentSelector.ScoreOrCondition) { 1605 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait) 1606 << getOpenMPContextTraitPropertyName( 1607 ParentProperty.Kind, ParentProperty.RawString) 1608 << getOpenMPContextTraitSelectorName(ParentSelector.Kind) 1609 << getOpenMPContextTraitSetName(ParentSet.Kind); 1610 } 1611 } 1612 if (!MergedProperty) 1613 Selector.Properties.push_back(ParentProperty); 1614 } 1615 } 1616 if (!MergedSelector) 1617 Set.Selectors.push_back(ParentSelector); 1618 } 1619 } 1620 if (!MergedSet) 1621 TI.Sets.push_back(ParentSet); 1622 } 1623 1624 return false; 1625 } 1626 1627 /// <clause> [clause[ [,] clause] ... ] 1628 /// 1629 /// clauses: for error directive 1630 /// 'at' '(' compilation | execution ')' 1631 /// 'severity' '(' fatal | warning ')' 1632 /// 'message' '(' msg-string ')' 1633 /// .... 1634 void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind, 1635 SmallVectorImpl<OMPClause *> &Clauses, 1636 SourceLocation Loc) { 1637 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1638 llvm::omp::Clause_enumSize + 1> 1639 FirstClauses(llvm::omp::Clause_enumSize + 1); 1640 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1641 OpenMPClauseKind CKind = Tok.isAnnotation() 1642 ? OMPC_unknown 1643 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1644 Actions.StartOpenMPClause(CKind); 1645 OMPClause *Clause = ParseOpenMPClause( 1646 DKind, CKind, !FirstClauses[unsigned(CKind)].getInt()); 1647 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1648 StopBeforeMatch); 1649 FirstClauses[unsigned(CKind)].setInt(true); 1650 if (Clause != nullptr) 1651 Clauses.push_back(Clause); 1652 if (Tok.is(tok::annot_pragma_openmp_end)) { 1653 Actions.EndOpenMPClause(); 1654 break; 1655 } 1656 // Skip ',' if any. 1657 if (Tok.is(tok::comma)) 1658 ConsumeToken(); 1659 Actions.EndOpenMPClause(); 1660 } 1661 } 1662 1663 /// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]... 1664 /// where 1665 /// 1666 /// clause: 1667 /// 'ext_IMPL_DEFINED' 1668 /// 'absent' '(' directive-name [, directive-name]* ')' 1669 /// 'contains' '(' directive-name [, directive-name]* ')' 1670 /// 'holds' '(' scalar-expression ')' 1671 /// 'no_openmp' 1672 /// 'no_openmp_routines' 1673 /// 'no_parallelism' 1674 /// 1675 void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind, 1676 SourceLocation Loc) { 1677 SmallVector<std::string, 4> Assumptions; 1678 bool SkippedClauses = false; 1679 1680 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) { 1681 BalancedDelimiterTracker T(*this, tok::l_paren, 1682 tok::annot_pragma_openmp_end); 1683 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data())) 1684 return; 1685 T.skipToEnd(); 1686 if (IssueNote && T.getCloseLocation().isValid()) 1687 Diag(T.getCloseLocation(), 1688 diag::note_omp_assumption_clause_continue_here); 1689 }; 1690 1691 /// Helper to determine which AssumptionClauseMapping (ACM) in the 1692 /// AssumptionClauseMappings table matches \p RawString. The return value is 1693 /// the index of the matching ACM into the table or -1 if there was no match. 1694 auto MatchACMClause = [&](StringRef RawString) { 1695 llvm::StringSwitch<int> SS(RawString); 1696 unsigned ACMIdx = 0; 1697 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) { 1698 if (ACMI.StartsWith) 1699 SS.StartsWith(ACMI.Identifier, ACMIdx++); 1700 else 1701 SS.Case(ACMI.Identifier, ACMIdx++); 1702 } 1703 return SS.Default(-1); 1704 }; 1705 1706 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1707 IdentifierInfo *II = nullptr; 1708 SourceLocation StartLoc = Tok.getLocation(); 1709 int Idx = -1; 1710 if (Tok.isAnyIdentifier()) { 1711 II = Tok.getIdentifierInfo(); 1712 Idx = MatchACMClause(II->getName()); 1713 } 1714 ConsumeAnyToken(); 1715 1716 bool NextIsLPar = Tok.is(tok::l_paren); 1717 // Handle unknown clauses by skipping them. 1718 if (Idx == -1) { 1719 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id) 1720 << llvm::omp::getOpenMPDirectiveName(DKind) 1721 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar; 1722 if (NextIsLPar) 1723 SkipBraces(II ? II->getName() : "", /* IssueNote */ true); 1724 SkippedClauses = true; 1725 continue; 1726 } 1727 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx]; 1728 if (ACMI.HasDirectiveList || ACMI.HasExpression) { 1729 // TODO: We ignore absent, contains, and holds assumptions for now. We 1730 // also do not verify the content in the parenthesis at all. 1731 SkippedClauses = true; 1732 SkipBraces(II->getName(), /* IssueNote */ false); 1733 continue; 1734 } 1735 1736 if (NextIsLPar) { 1737 Diag(Tok.getLocation(), 1738 diag::warn_omp_unknown_assumption_clause_without_args) 1739 << II; 1740 SkipBraces(II->getName(), /* IssueNote */ true); 1741 } 1742 1743 assert(II && "Expected an identifier clause!"); 1744 std::string Assumption = II->getName().str(); 1745 if (ACMI.StartsWith) 1746 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size()); 1747 else 1748 Assumption = "omp_" + Assumption; 1749 Assumptions.push_back(Assumption); 1750 } 1751 1752 Actions.ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions, SkippedClauses); 1753 } 1754 1755 void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) { 1756 if (Actions.isInOpenMPAssumeScope()) 1757 Actions.ActOnOpenMPEndAssumesDirective(); 1758 else 1759 Diag(Loc, diag::err_expected_begin_assumes); 1760 } 1761 1762 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1763 /// 1764 /// default-clause: 1765 /// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ') 1766 /// 1767 /// proc_bind-clause: 1768 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1769 /// 1770 /// device_type-clause: 1771 /// 'device_type' '(' 'host' | 'nohost' | 'any' )' 1772 namespace { 1773 struct SimpleClauseData { 1774 unsigned Type; 1775 SourceLocation Loc; 1776 SourceLocation LOpen; 1777 SourceLocation TypeLoc; 1778 SourceLocation RLoc; 1779 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, 1780 SourceLocation TypeLoc, SourceLocation RLoc) 1781 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} 1782 }; 1783 } // anonymous namespace 1784 1785 static std::optional<SimpleClauseData> 1786 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { 1787 const Token &Tok = P.getCurToken(); 1788 SourceLocation Loc = Tok.getLocation(); 1789 SourceLocation LOpen = P.ConsumeToken(); 1790 // Parse '('. 1791 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 1792 if (T.expectAndConsume(diag::err_expected_lparen_after, 1793 getOpenMPClauseName(Kind).data())) 1794 return std::nullopt; 1795 1796 unsigned Type = getOpenMPSimpleClauseType( 1797 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok), 1798 P.getLangOpts()); 1799 SourceLocation TypeLoc = Tok.getLocation(); 1800 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1801 Tok.isNot(tok::annot_pragma_openmp_end)) 1802 P.ConsumeAnyToken(); 1803 1804 // Parse ')'. 1805 SourceLocation RLoc = Tok.getLocation(); 1806 if (!T.consumeClose()) 1807 RLoc = T.getCloseLocation(); 1808 1809 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); 1810 } 1811 1812 void Parser::ParseOMPDeclareTargetClauses( 1813 Sema::DeclareTargetContextInfo &DTCI) { 1814 SourceLocation DeviceTypeLoc; 1815 bool RequiresToOrLinkOrIndirectClause = false; 1816 bool HasToOrLinkOrIndirectClause = false; 1817 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1818 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 1819 bool HasIdentifier = Tok.is(tok::identifier); 1820 if (HasIdentifier) { 1821 // If we see any clause we need a to or link clause. 1822 RequiresToOrLinkOrIndirectClause = true; 1823 IdentifierInfo *II = Tok.getIdentifierInfo(); 1824 StringRef ClauseName = II->getName(); 1825 bool IsDeviceTypeClause = 1826 getLangOpts().OpenMP >= 50 && 1827 getOpenMPClauseKind(ClauseName) == OMPC_device_type; 1828 1829 bool IsIndirectClause = getLangOpts().OpenMP >= 51 && 1830 getOpenMPClauseKind(ClauseName) == OMPC_indirect; 1831 if (DTCI.Indirect && IsIndirectClause) { 1832 Diag(Tok, diag::err_omp_more_one_clause) 1833 << getOpenMPDirectiveName(OMPD_declare_target) 1834 << getOpenMPClauseName(OMPC_indirect) << 0; 1835 break; 1836 } 1837 bool IsToEnterOrLinkClause = 1838 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT); 1839 assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) && 1840 "Cannot be both!"); 1841 1842 // Starting with OpenMP 5.2 the `to` clause has been replaced by the 1843 // `enter` clause. 1844 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") { 1845 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause); 1846 break; 1847 } 1848 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") { 1849 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause); 1850 break; 1851 } 1852 1853 if (!IsDeviceTypeClause && !IsIndirectClause && 1854 DTCI.Kind == OMPD_begin_declare_target) { 1855 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1856 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0); 1857 break; 1858 } 1859 if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) { 1860 Diag(Tok, getLangOpts().OpenMP >= 52 1861 ? diag::err_omp_declare_target_unexpected_clause_52 1862 : diag::err_omp_declare_target_unexpected_clause) 1863 << ClauseName 1864 << (getLangOpts().OpenMP >= 51 1865 ? 4 1866 : getLangOpts().OpenMP >= 50 ? 2 : 1); 1867 break; 1868 } 1869 1870 if (IsToEnterOrLinkClause || IsIndirectClause) 1871 HasToOrLinkOrIndirectClause = true; 1872 1873 if (IsIndirectClause) { 1874 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false)) 1875 break; 1876 continue; 1877 } 1878 // Parse 'device_type' clause and go to next clause if any. 1879 if (IsDeviceTypeClause) { 1880 std::optional<SimpleClauseData> DevTypeData = 1881 parseOpenMPSimpleClause(*this, OMPC_device_type); 1882 if (DevTypeData) { 1883 if (DeviceTypeLoc.isValid()) { 1884 // We already saw another device_type clause, diagnose it. 1885 Diag(DevTypeData->Loc, 1886 diag::warn_omp_more_one_device_type_clause); 1887 break; 1888 } 1889 switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) { 1890 case OMPC_DEVICE_TYPE_any: 1891 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any; 1892 break; 1893 case OMPC_DEVICE_TYPE_host: 1894 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host; 1895 break; 1896 case OMPC_DEVICE_TYPE_nohost: 1897 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost; 1898 break; 1899 case OMPC_DEVICE_TYPE_unknown: 1900 llvm_unreachable("Unexpected device_type"); 1901 } 1902 DeviceTypeLoc = DevTypeData->Loc; 1903 } 1904 continue; 1905 } 1906 ConsumeToken(); 1907 } 1908 1909 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) { 1910 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS, 1911 DeclarationNameInfo NameInfo) { 1912 NamedDecl *ND = 1913 Actions.lookupOpenMPDeclareTargetName(getCurScope(), SS, NameInfo); 1914 if (!ND) 1915 return; 1916 Sema::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()}; 1917 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second; 1918 if (!FirstMapping) 1919 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple) 1920 << NameInfo.getName(); 1921 }; 1922 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 1923 /*AllowScopeSpecifier=*/true)) 1924 break; 1925 } 1926 1927 if (Tok.is(tok::l_paren)) { 1928 Diag(Tok, 1929 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause); 1930 break; 1931 } 1932 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) { 1933 Diag(Tok, 1934 getLangOpts().OpenMP >= 52 1935 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter 1936 : diag::err_omp_declare_target_wrong_clause_after_implicit_to); 1937 break; 1938 } 1939 1940 // Consume optional ','. 1941 if (Tok.is(tok::comma)) 1942 ConsumeToken(); 1943 } 1944 1945 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any) 1946 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type); 1947 1948 // For declare target require at least 'to' or 'link' to be present. 1949 if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause && 1950 !HasToOrLinkOrIndirectClause) 1951 Diag(DTCI.Loc, 1952 getLangOpts().OpenMP >= 52 1953 ? diag::err_omp_declare_target_missing_enter_or_link_clause 1954 : diag::err_omp_declare_target_missing_to_or_link_clause) 1955 << (getLangOpts().OpenMP >= 51 ? 1 : 0); 1956 1957 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1958 } 1959 1960 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) { 1961 // The last seen token is annot_pragma_openmp_end - need to check for 1962 // extra tokens. 1963 if (Tok.is(tok::annot_pragma_openmp_end)) 1964 return; 1965 1966 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1967 << getOpenMPDirectiveName(DKind); 1968 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1969 ConsumeAnyToken(); 1970 } 1971 1972 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind, 1973 OpenMPDirectiveKind ExpectedKind, 1974 OpenMPDirectiveKind FoundKind, 1975 SourceLocation BeginLoc, 1976 SourceLocation FoundLoc, 1977 bool SkipUntilOpenMPEnd) { 1978 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1; 1979 1980 if (FoundKind == ExpectedKind) { 1981 ConsumeAnyToken(); 1982 skipUntilPragmaOpenMPEnd(ExpectedKind); 1983 return; 1984 } 1985 1986 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant) 1987 << DiagSelection; 1988 Diag(BeginLoc, diag::note_matching) 1989 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str(); 1990 if (SkipUntilOpenMPEnd) 1991 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1992 } 1993 1994 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind, 1995 OpenMPDirectiveKind EndDKind, 1996 SourceLocation DKLoc) { 1997 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc, 1998 Tok.getLocation(), 1999 /* SkipUntilOpenMPEnd */ false); 2000 // Skip the last annot_pragma_openmp_end. 2001 if (Tok.is(tok::annot_pragma_openmp_end)) 2002 ConsumeAnnotationToken(); 2003 } 2004 2005 /// Parsing of declarative OpenMP directives. 2006 /// 2007 /// threadprivate-directive: 2008 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2009 /// annot_pragma_openmp_end 2010 /// 2011 /// allocate-directive: 2012 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 2013 /// annot_pragma_openmp_end 2014 /// 2015 /// declare-reduction-directive: 2016 /// annot_pragma_openmp 'declare' 'reduction' [...] 2017 /// annot_pragma_openmp_end 2018 /// 2019 /// declare-mapper-directive: 2020 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2021 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2022 /// annot_pragma_openmp_end 2023 /// 2024 /// declare-simd-directive: 2025 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 2026 /// annot_pragma_openmp_end 2027 /// <function declaration/definition> 2028 /// 2029 /// requires directive: 2030 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 2031 /// annot_pragma_openmp_end 2032 /// 2033 /// assumes directive: 2034 /// annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ] 2035 /// annot_pragma_openmp_end 2036 /// or 2037 /// annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ] 2038 /// annot_pragma_openmp 'end assumes' 2039 /// annot_pragma_openmp_end 2040 /// 2041 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 2042 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed, 2043 DeclSpec::TST TagType, Decl *Tag) { 2044 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && 2045 "Not an OpenMP directive!"); 2046 ParsingOpenMPDirectiveRAII DirScope(*this); 2047 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2048 2049 SourceLocation Loc; 2050 OpenMPDirectiveKind DKind; 2051 if (Delayed) { 2052 TentativeParsingAction TPA(*this); 2053 Loc = ConsumeAnnotationToken(); 2054 DKind = parseOpenMPDirectiveKind(*this); 2055 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { 2056 // Need to delay parsing until completion of the parent class. 2057 TPA.Revert(); 2058 CachedTokens Toks; 2059 unsigned Cnt = 1; 2060 Toks.push_back(Tok); 2061 while (Cnt && Tok.isNot(tok::eof)) { 2062 (void)ConsumeAnyToken(); 2063 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) 2064 ++Cnt; 2065 else if (Tok.is(tok::annot_pragma_openmp_end)) 2066 --Cnt; 2067 Toks.push_back(Tok); 2068 } 2069 // Skip last annot_pragma_openmp_end. 2070 if (Cnt == 0) 2071 (void)ConsumeAnyToken(); 2072 auto *LP = new LateParsedPragma(this, AS); 2073 LP->takeToks(Toks); 2074 getCurrentClass().LateParsedDeclarations.push_back(LP); 2075 return nullptr; 2076 } 2077 TPA.Commit(); 2078 } else { 2079 Loc = ConsumeAnnotationToken(); 2080 DKind = parseOpenMPDirectiveKind(*this); 2081 } 2082 2083 switch (DKind) { 2084 case OMPD_threadprivate: { 2085 ConsumeToken(); 2086 DeclDirectiveListParserHelper Helper(this, DKind); 2087 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2088 /*AllowScopeSpecifier=*/true)) { 2089 skipUntilPragmaOpenMPEnd(DKind); 2090 // Skip the last annot_pragma_openmp_end. 2091 ConsumeAnnotationToken(); 2092 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 2093 Helper.getIdentifiers()); 2094 } 2095 break; 2096 } 2097 case OMPD_allocate: { 2098 ConsumeToken(); 2099 DeclDirectiveListParserHelper Helper(this, DKind); 2100 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2101 /*AllowScopeSpecifier=*/true)) { 2102 SmallVector<OMPClause *, 1> Clauses; 2103 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2104 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2105 llvm::omp::Clause_enumSize + 1> 2106 FirstClauses(llvm::omp::Clause_enumSize + 1); 2107 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2108 OpenMPClauseKind CKind = 2109 Tok.isAnnotation() ? OMPC_unknown 2110 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2111 Actions.StartOpenMPClause(CKind); 2112 OMPClause *Clause = ParseOpenMPClause( 2113 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2114 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2115 StopBeforeMatch); 2116 FirstClauses[unsigned(CKind)].setInt(true); 2117 if (Clause != nullptr) 2118 Clauses.push_back(Clause); 2119 if (Tok.is(tok::annot_pragma_openmp_end)) { 2120 Actions.EndOpenMPClause(); 2121 break; 2122 } 2123 // Skip ',' if any. 2124 if (Tok.is(tok::comma)) 2125 ConsumeToken(); 2126 Actions.EndOpenMPClause(); 2127 } 2128 skipUntilPragmaOpenMPEnd(DKind); 2129 } 2130 // Skip the last annot_pragma_openmp_end. 2131 ConsumeAnnotationToken(); 2132 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 2133 Clauses); 2134 } 2135 break; 2136 } 2137 case OMPD_requires: { 2138 SourceLocation StartLoc = ConsumeToken(); 2139 SmallVector<OMPClause *, 5> Clauses; 2140 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2141 llvm::omp::Clause_enumSize + 1> 2142 FirstClauses(llvm::omp::Clause_enumSize + 1); 2143 if (Tok.is(tok::annot_pragma_openmp_end)) { 2144 Diag(Tok, diag::err_omp_expected_clause) 2145 << getOpenMPDirectiveName(OMPD_requires); 2146 break; 2147 } 2148 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2149 OpenMPClauseKind CKind = Tok.isAnnotation() 2150 ? OMPC_unknown 2151 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2152 Actions.StartOpenMPClause(CKind); 2153 OMPClause *Clause = ParseOpenMPClause( 2154 OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2155 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2156 StopBeforeMatch); 2157 FirstClauses[unsigned(CKind)].setInt(true); 2158 if (Clause != nullptr) 2159 Clauses.push_back(Clause); 2160 if (Tok.is(tok::annot_pragma_openmp_end)) { 2161 Actions.EndOpenMPClause(); 2162 break; 2163 } 2164 // Skip ',' if any. 2165 if (Tok.is(tok::comma)) 2166 ConsumeToken(); 2167 Actions.EndOpenMPClause(); 2168 } 2169 // Consume final annot_pragma_openmp_end 2170 if (Clauses.empty()) { 2171 Diag(Tok, diag::err_omp_expected_clause) 2172 << getOpenMPDirectiveName(OMPD_requires); 2173 ConsumeAnnotationToken(); 2174 return nullptr; 2175 } 2176 ConsumeAnnotationToken(); 2177 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 2178 } 2179 case OMPD_error: { 2180 SmallVector<OMPClause *, 1> Clauses; 2181 SourceLocation StartLoc = ConsumeToken(); 2182 ParseOpenMPClauses(DKind, Clauses, StartLoc); 2183 Actions.ActOnOpenMPErrorDirective(Clauses, StartLoc, SourceLocation(), 2184 /*InExContext = */ false); 2185 break; 2186 } 2187 case OMPD_assumes: 2188 case OMPD_begin_assumes: 2189 ParseOpenMPAssumesDirective(DKind, ConsumeToken()); 2190 break; 2191 case OMPD_end_assumes: 2192 ParseOpenMPEndAssumesDirective(ConsumeToken()); 2193 break; 2194 case OMPD_declare_reduction: 2195 ConsumeToken(); 2196 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 2197 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2198 // Skip the last annot_pragma_openmp_end. 2199 ConsumeAnnotationToken(); 2200 return Res; 2201 } 2202 break; 2203 case OMPD_declare_mapper: { 2204 ConsumeToken(); 2205 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 2206 // Skip the last annot_pragma_openmp_end. 2207 ConsumeAnnotationToken(); 2208 return Res; 2209 } 2210 break; 2211 } 2212 case OMPD_begin_declare_variant: { 2213 // The syntax is: 2214 // { #pragma omp begin declare variant clause } 2215 // <function-declaration-or-definition-sequence> 2216 // { #pragma omp end declare variant } 2217 // 2218 ConsumeToken(); 2219 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope(); 2220 ASTContext &ASTCtx = Actions.getASTContext(); 2221 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); 2222 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) { 2223 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 2224 ; 2225 // Skip the last annot_pragma_openmp_end. 2226 (void)ConsumeAnnotationToken(); 2227 break; 2228 } 2229 2230 // Skip last tokens. 2231 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant); 2232 2233 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2234 2235 VariantMatchInfo VMI; 2236 TI.getAsVariantMatchInfo(ASTCtx, VMI); 2237 2238 std::function<void(StringRef)> DiagUnknownTrait = 2239 [this, Loc](StringRef ISATrait) { 2240 // TODO Track the selector locations in a way that is accessible here 2241 // to improve the diagnostic location. 2242 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; 2243 }; 2244 TargetOMPContext OMPCtx( 2245 ASTCtx, std::move(DiagUnknownTrait), 2246 /* CurrentFunctionDecl */ nullptr, 2247 /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>()); 2248 2249 if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) { 2250 Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI); 2251 break; 2252 } 2253 2254 // Elide all the code till the matching end declare variant was found. 2255 unsigned Nesting = 1; 2256 SourceLocation DKLoc; 2257 OpenMPDirectiveKind DK = OMPD_unknown; 2258 do { 2259 DKLoc = Tok.getLocation(); 2260 DK = parseOpenMPDirectiveKind(*this); 2261 if (DK == OMPD_end_declare_variant) 2262 --Nesting; 2263 else if (DK == OMPD_begin_declare_variant) 2264 ++Nesting; 2265 if (!Nesting || isEofOrEom()) 2266 break; 2267 ConsumeAnyToken(); 2268 } while (true); 2269 2270 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, 2271 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true); 2272 if (isEofOrEom()) 2273 return nullptr; 2274 break; 2275 } 2276 case OMPD_end_declare_variant: { 2277 if (Actions.isInOpenMPDeclareVariantScope()) 2278 Actions.ActOnOpenMPEndDeclareVariant(); 2279 else 2280 Diag(Loc, diag::err_expected_begin_declare_variant); 2281 ConsumeToken(); 2282 break; 2283 } 2284 case OMPD_declare_variant: 2285 case OMPD_declare_simd: { 2286 // The syntax is: 2287 // { #pragma omp declare {simd|variant} } 2288 // <function-declaration-or-definition> 2289 // 2290 CachedTokens Toks; 2291 Toks.push_back(Tok); 2292 ConsumeToken(); 2293 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2294 Toks.push_back(Tok); 2295 ConsumeAnyToken(); 2296 } 2297 Toks.push_back(Tok); 2298 ConsumeAnyToken(); 2299 2300 DeclGroupPtrTy Ptr; 2301 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) { 2302 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, 2303 TagType, Tag); 2304 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 2305 // Here we expect to see some function declaration. 2306 if (AS == AS_none) { 2307 assert(TagType == DeclSpec::TST_unspecified); 2308 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); 2309 MaybeParseCXX11Attributes(Attrs); 2310 ParsingDeclSpec PDS(*this); 2311 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS); 2312 } else { 2313 Ptr = 2314 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 2315 } 2316 } 2317 if (!Ptr) { 2318 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) 2319 << (DKind == OMPD_declare_simd ? 0 : 1); 2320 return DeclGroupPtrTy(); 2321 } 2322 if (DKind == OMPD_declare_simd) 2323 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 2324 assert(DKind == OMPD_declare_variant && 2325 "Expected declare variant directive only"); 2326 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); 2327 return Ptr; 2328 } 2329 case OMPD_begin_declare_target: 2330 case OMPD_declare_target: { 2331 SourceLocation DTLoc = ConsumeAnyToken(); 2332 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end); 2333 Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc); 2334 if (HasClauses) 2335 ParseOMPDeclareTargetClauses(DTCI); 2336 bool HasImplicitMappings = DKind == OMPD_begin_declare_target || 2337 !HasClauses || 2338 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect); 2339 2340 // Skip the last annot_pragma_openmp_end. 2341 ConsumeAnyToken(); 2342 2343 if (HasImplicitMappings) { 2344 Actions.ActOnStartOpenMPDeclareTargetContext(DTCI); 2345 return nullptr; 2346 } 2347 2348 Actions.ActOnFinishedOpenMPDeclareTargetContext(DTCI); 2349 llvm::SmallVector<Decl *, 4> Decls; 2350 for (auto &It : DTCI.ExplicitlyMapped) 2351 Decls.push_back(It.first); 2352 return Actions.BuildDeclaratorGroup(Decls); 2353 } 2354 case OMPD_end_declare_target: { 2355 if (!Actions.isInOpenMPDeclareTargetContext()) { 2356 Diag(Tok, diag::err_omp_unexpected_directive) 2357 << 1 << getOpenMPDirectiveName(DKind); 2358 break; 2359 } 2360 const Sema::DeclareTargetContextInfo &DTCI = 2361 Actions.ActOnOpenMPEndDeclareTargetDirective(); 2362 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc); 2363 return nullptr; 2364 } 2365 case OMPD_unknown: 2366 Diag(Tok, diag::err_omp_unknown_directive); 2367 break; 2368 case OMPD_parallel: 2369 case OMPD_simd: 2370 case OMPD_tile: 2371 case OMPD_unroll: 2372 case OMPD_task: 2373 case OMPD_taskyield: 2374 case OMPD_barrier: 2375 case OMPD_taskwait: 2376 case OMPD_taskgroup: 2377 case OMPD_flush: 2378 case OMPD_depobj: 2379 case OMPD_scan: 2380 case OMPD_for: 2381 case OMPD_for_simd: 2382 case OMPD_sections: 2383 case OMPD_section: 2384 case OMPD_single: 2385 case OMPD_master: 2386 case OMPD_ordered: 2387 case OMPD_critical: 2388 case OMPD_parallel_for: 2389 case OMPD_parallel_for_simd: 2390 case OMPD_parallel_sections: 2391 case OMPD_parallel_master: 2392 case OMPD_parallel_masked: 2393 case OMPD_atomic: 2394 case OMPD_target: 2395 case OMPD_teams: 2396 case OMPD_cancellation_point: 2397 case OMPD_cancel: 2398 case OMPD_target_data: 2399 case OMPD_target_enter_data: 2400 case OMPD_target_exit_data: 2401 case OMPD_target_parallel: 2402 case OMPD_target_parallel_for: 2403 case OMPD_taskloop: 2404 case OMPD_taskloop_simd: 2405 case OMPD_master_taskloop: 2406 case OMPD_master_taskloop_simd: 2407 case OMPD_parallel_master_taskloop: 2408 case OMPD_parallel_master_taskloop_simd: 2409 case OMPD_masked_taskloop: 2410 case OMPD_masked_taskloop_simd: 2411 case OMPD_parallel_masked_taskloop: 2412 case OMPD_parallel_masked_taskloop_simd: 2413 case OMPD_distribute: 2414 case OMPD_target_update: 2415 case OMPD_distribute_parallel_for: 2416 case OMPD_distribute_parallel_for_simd: 2417 case OMPD_distribute_simd: 2418 case OMPD_target_parallel_for_simd: 2419 case OMPD_target_simd: 2420 case OMPD_teams_distribute: 2421 case OMPD_teams_distribute_simd: 2422 case OMPD_teams_distribute_parallel_for_simd: 2423 case OMPD_teams_distribute_parallel_for: 2424 case OMPD_target_teams: 2425 case OMPD_target_teams_distribute: 2426 case OMPD_target_teams_distribute_parallel_for: 2427 case OMPD_target_teams_distribute_parallel_for_simd: 2428 case OMPD_target_teams_distribute_simd: 2429 case OMPD_dispatch: 2430 case OMPD_masked: 2431 case OMPD_metadirective: 2432 case OMPD_loop: 2433 case OMPD_teams_loop: 2434 case OMPD_target_teams_loop: 2435 case OMPD_parallel_loop: 2436 case OMPD_target_parallel_loop: 2437 Diag(Tok, diag::err_omp_unexpected_directive) 2438 << 1 << getOpenMPDirectiveName(DKind); 2439 break; 2440 default: 2441 break; 2442 } 2443 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2444 ConsumeAnyToken(); 2445 ConsumeAnyToken(); 2446 return nullptr; 2447 } 2448 2449 /// Parsing of declarative or executable OpenMP directives. 2450 /// 2451 /// threadprivate-directive: 2452 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2453 /// annot_pragma_openmp_end 2454 /// 2455 /// allocate-directive: 2456 /// annot_pragma_openmp 'allocate' simple-variable-list 2457 /// annot_pragma_openmp_end 2458 /// 2459 /// declare-reduction-directive: 2460 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 2461 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 2462 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 2463 /// annot_pragma_openmp_end 2464 /// 2465 /// declare-mapper-directive: 2466 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2467 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2468 /// annot_pragma_openmp_end 2469 /// 2470 /// executable-directive: 2471 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 2472 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 2473 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | 2474 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error' 2475 /// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target 2476 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 2477 /// 'master taskloop' | 'master taskloop simd' | 'parallel master 2478 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target 2479 /// enter data' | 'target exit data' | 'target parallel' | 'target 2480 /// parallel for' | 'target update' | 'distribute parallel for' | 2481 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel 2482 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute 2483 /// simd' | 'teams distribute parallel for simd' | 'teams distribute 2484 /// parallel for' | 'target teams' | 'target teams distribute' | 'target 2485 /// teams distribute parallel for' | 'target teams distribute parallel 2486 /// for simd' | 'target teams distribute simd' | 'masked' {clause} 2487 /// annot_pragma_openmp_end 2488 /// 2489 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( 2490 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) { 2491 if (!ReadDirectiveWithinMetadirective) 2492 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && 2493 "Not an OpenMP directive!"); 2494 ParsingOpenMPDirectiveRAII DirScope(*this); 2495 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2496 SmallVector<OMPClause *, 5> Clauses; 2497 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2498 llvm::omp::Clause_enumSize + 1> 2499 FirstClauses(llvm::omp::Clause_enumSize + 1); 2500 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 2501 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 2502 SourceLocation Loc = ReadDirectiveWithinMetadirective 2503 ? Tok.getLocation() 2504 : ConsumeAnnotationToken(), 2505 EndLoc; 2506 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 2507 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) { 2508 Diag(Tok, diag::err_omp_unknown_directive); 2509 return StmtError(); 2510 } 2511 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 2512 // Name of critical directive. 2513 DeclarationNameInfo DirName; 2514 StmtResult Directive = StmtError(); 2515 bool HasAssociatedStatement = true; 2516 2517 switch (DKind) { 2518 case OMPD_nothing: 2519 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2520 ParsedStmtContext()) 2521 Diag(Tok, diag::err_omp_immediate_directive) 2522 << getOpenMPDirectiveName(DKind) << 0; 2523 ConsumeToken(); 2524 skipUntilPragmaOpenMPEnd(DKind); 2525 if (Tok.is(tok::annot_pragma_openmp_end)) 2526 ConsumeAnnotationToken(); 2527 break; 2528 case OMPD_metadirective: { 2529 ConsumeToken(); 2530 SmallVector<VariantMatchInfo, 4> VMIs; 2531 2532 // First iteration of parsing all clauses of metadirective. 2533 // This iteration only parses and collects all context selector ignoring the 2534 // associated directives. 2535 TentativeParsingAction TPA(*this); 2536 ASTContext &ASTContext = Actions.getASTContext(); 2537 2538 BalancedDelimiterTracker T(*this, tok::l_paren, 2539 tok::annot_pragma_openmp_end); 2540 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2541 OpenMPClauseKind CKind = Tok.isAnnotation() 2542 ? OMPC_unknown 2543 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2544 SourceLocation Loc = ConsumeToken(); 2545 2546 // Parse '('. 2547 if (T.expectAndConsume(diag::err_expected_lparen_after, 2548 getOpenMPClauseName(CKind).data())) 2549 return Directive; 2550 2551 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 2552 if (CKind == OMPC_when) { 2553 // parse and get OMPTraitInfo to pass to the When clause 2554 parseOMPContextSelectors(Loc, TI); 2555 if (TI.Sets.size() == 0) { 2556 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause"; 2557 TPA.Commit(); 2558 return Directive; 2559 } 2560 2561 // Parse ':' 2562 if (Tok.is(tok::colon)) 2563 ConsumeAnyToken(); 2564 else { 2565 Diag(Tok, diag::err_omp_expected_colon) << "when clause"; 2566 TPA.Commit(); 2567 return Directive; 2568 } 2569 } 2570 // Skip Directive for now. We will parse directive in the second iteration 2571 int paren = 0; 2572 while (Tok.isNot(tok::r_paren) || paren != 0) { 2573 if (Tok.is(tok::l_paren)) 2574 paren++; 2575 if (Tok.is(tok::r_paren)) 2576 paren--; 2577 if (Tok.is(tok::annot_pragma_openmp_end)) { 2578 Diag(Tok, diag::err_omp_expected_punc) 2579 << getOpenMPClauseName(CKind) << 0; 2580 TPA.Commit(); 2581 return Directive; 2582 } 2583 ConsumeAnyToken(); 2584 } 2585 // Parse ')' 2586 if (Tok.is(tok::r_paren)) 2587 T.consumeClose(); 2588 2589 VariantMatchInfo VMI; 2590 TI.getAsVariantMatchInfo(ASTContext, VMI); 2591 2592 VMIs.push_back(VMI); 2593 } 2594 2595 TPA.Revert(); 2596 // End of the first iteration. Parser is reset to the start of metadirective 2597 2598 std::function<void(StringRef)> DiagUnknownTrait = 2599 [this, Loc](StringRef ISATrait) { 2600 // TODO Track the selector locations in a way that is accessible here 2601 // to improve the diagnostic location. 2602 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; 2603 }; 2604 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait), 2605 /* CurrentFunctionDecl */ nullptr, 2606 ArrayRef<llvm::omp::TraitProperty>()); 2607 2608 // A single match is returned for OpenMP 5.0 2609 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx); 2610 2611 int Idx = 0; 2612 // In OpenMP 5.0 metadirective is either replaced by another directive or 2613 // ignored. 2614 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches 2615 // found by getBestWhenMatchForContext. 2616 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2617 // OpenMP 5.0 implementation - Skip to the best index found. 2618 if (Idx++ != BestIdx) { 2619 ConsumeToken(); // Consume clause name 2620 T.consumeOpen(); // Consume '(' 2621 int paren = 0; 2622 // Skip everything inside the clause 2623 while (Tok.isNot(tok::r_paren) || paren != 0) { 2624 if (Tok.is(tok::l_paren)) 2625 paren++; 2626 if (Tok.is(tok::r_paren)) 2627 paren--; 2628 ConsumeAnyToken(); 2629 } 2630 // Parse ')' 2631 if (Tok.is(tok::r_paren)) 2632 T.consumeClose(); 2633 continue; 2634 } 2635 2636 OpenMPClauseKind CKind = Tok.isAnnotation() 2637 ? OMPC_unknown 2638 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2639 SourceLocation Loc = ConsumeToken(); 2640 2641 // Parse '('. 2642 T.consumeOpen(); 2643 2644 // Skip ContextSelectors for when clause 2645 if (CKind == OMPC_when) { 2646 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 2647 // parse and skip the ContextSelectors 2648 parseOMPContextSelectors(Loc, TI); 2649 2650 // Parse ':' 2651 ConsumeAnyToken(); 2652 } 2653 2654 // If no directive is passed, skip in OpenMP 5.0. 2655 // TODO: Generate nothing directive from OpenMP 5.1. 2656 if (Tok.is(tok::r_paren)) { 2657 SkipUntil(tok::annot_pragma_openmp_end); 2658 break; 2659 } 2660 2661 // Parse Directive 2662 Directive = ParseOpenMPDeclarativeOrExecutableDirective( 2663 StmtCtx, 2664 /*ReadDirectiveWithinMetadirective=*/true); 2665 break; 2666 } 2667 break; 2668 } 2669 case OMPD_threadprivate: { 2670 // FIXME: Should this be permitted in C++? 2671 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2672 ParsedStmtContext()) { 2673 Diag(Tok, diag::err_omp_immediate_directive) 2674 << getOpenMPDirectiveName(DKind) << 0; 2675 } 2676 ConsumeToken(); 2677 DeclDirectiveListParserHelper Helper(this, DKind); 2678 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2679 /*AllowScopeSpecifier=*/false)) { 2680 skipUntilPragmaOpenMPEnd(DKind); 2681 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 2682 Loc, Helper.getIdentifiers()); 2683 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2684 } 2685 SkipUntil(tok::annot_pragma_openmp_end); 2686 break; 2687 } 2688 case OMPD_allocate: { 2689 // FIXME: Should this be permitted in C++? 2690 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2691 ParsedStmtContext()) { 2692 Diag(Tok, diag::err_omp_immediate_directive) 2693 << getOpenMPDirectiveName(DKind) << 0; 2694 } 2695 ConsumeToken(); 2696 DeclDirectiveListParserHelper Helper(this, DKind); 2697 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2698 /*AllowScopeSpecifier=*/false)) { 2699 SmallVector<OMPClause *, 1> Clauses; 2700 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2701 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2702 llvm::omp::Clause_enumSize + 1> 2703 FirstClauses(llvm::omp::Clause_enumSize + 1); 2704 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2705 OpenMPClauseKind CKind = 2706 Tok.isAnnotation() ? OMPC_unknown 2707 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2708 Actions.StartOpenMPClause(CKind); 2709 OMPClause *Clause = ParseOpenMPClause( 2710 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2711 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2712 StopBeforeMatch); 2713 FirstClauses[unsigned(CKind)].setInt(true); 2714 if (Clause != nullptr) 2715 Clauses.push_back(Clause); 2716 if (Tok.is(tok::annot_pragma_openmp_end)) { 2717 Actions.EndOpenMPClause(); 2718 break; 2719 } 2720 // Skip ',' if any. 2721 if (Tok.is(tok::comma)) 2722 ConsumeToken(); 2723 Actions.EndOpenMPClause(); 2724 } 2725 skipUntilPragmaOpenMPEnd(DKind); 2726 } 2727 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 2728 Loc, Helper.getIdentifiers(), Clauses); 2729 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2730 } 2731 SkipUntil(tok::annot_pragma_openmp_end); 2732 break; 2733 } 2734 case OMPD_declare_reduction: 2735 ConsumeToken(); 2736 if (DeclGroupPtrTy Res = 2737 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 2738 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2739 ConsumeAnyToken(); 2740 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2741 } else { 2742 SkipUntil(tok::annot_pragma_openmp_end); 2743 } 2744 break; 2745 case OMPD_declare_mapper: { 2746 ConsumeToken(); 2747 if (DeclGroupPtrTy Res = 2748 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 2749 // Skip the last annot_pragma_openmp_end. 2750 ConsumeAnnotationToken(); 2751 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2752 } else { 2753 SkipUntil(tok::annot_pragma_openmp_end); 2754 } 2755 break; 2756 } 2757 case OMPD_flush: 2758 case OMPD_depobj: 2759 case OMPD_scan: 2760 case OMPD_taskyield: 2761 case OMPD_error: 2762 case OMPD_barrier: 2763 case OMPD_taskwait: 2764 case OMPD_cancellation_point: 2765 case OMPD_cancel: 2766 case OMPD_target_enter_data: 2767 case OMPD_target_exit_data: 2768 case OMPD_target_update: 2769 case OMPD_interop: 2770 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2771 ParsedStmtContext()) { 2772 Diag(Tok, diag::err_omp_immediate_directive) 2773 << getOpenMPDirectiveName(DKind) << 0; 2774 if (DKind == OMPD_error) { 2775 SkipUntil(tok::annot_pragma_openmp_end); 2776 break; 2777 } 2778 } 2779 HasAssociatedStatement = false; 2780 // Fall through for further analysis. 2781 [[fallthrough]]; 2782 case OMPD_parallel: 2783 case OMPD_simd: 2784 case OMPD_tile: 2785 case OMPD_unroll: 2786 case OMPD_for: 2787 case OMPD_for_simd: 2788 case OMPD_sections: 2789 case OMPD_single: 2790 case OMPD_section: 2791 case OMPD_master: 2792 case OMPD_critical: 2793 case OMPD_parallel_for: 2794 case OMPD_parallel_for_simd: 2795 case OMPD_parallel_sections: 2796 case OMPD_parallel_master: 2797 case OMPD_parallel_masked: 2798 case OMPD_task: 2799 case OMPD_ordered: 2800 case OMPD_atomic: 2801 case OMPD_target: 2802 case OMPD_teams: 2803 case OMPD_taskgroup: 2804 case OMPD_target_data: 2805 case OMPD_target_parallel: 2806 case OMPD_target_parallel_for: 2807 case OMPD_loop: 2808 case OMPD_teams_loop: 2809 case OMPD_target_teams_loop: 2810 case OMPD_parallel_loop: 2811 case OMPD_target_parallel_loop: 2812 case OMPD_taskloop: 2813 case OMPD_taskloop_simd: 2814 case OMPD_master_taskloop: 2815 case OMPD_masked_taskloop: 2816 case OMPD_master_taskloop_simd: 2817 case OMPD_masked_taskloop_simd: 2818 case OMPD_parallel_master_taskloop: 2819 case OMPD_parallel_masked_taskloop: 2820 case OMPD_parallel_master_taskloop_simd: 2821 case OMPD_parallel_masked_taskloop_simd: 2822 case OMPD_distribute: 2823 case OMPD_distribute_parallel_for: 2824 case OMPD_distribute_parallel_for_simd: 2825 case OMPD_distribute_simd: 2826 case OMPD_target_parallel_for_simd: 2827 case OMPD_target_simd: 2828 case OMPD_teams_distribute: 2829 case OMPD_teams_distribute_simd: 2830 case OMPD_teams_distribute_parallel_for_simd: 2831 case OMPD_teams_distribute_parallel_for: 2832 case OMPD_target_teams: 2833 case OMPD_target_teams_distribute: 2834 case OMPD_target_teams_distribute_parallel_for: 2835 case OMPD_target_teams_distribute_parallel_for_simd: 2836 case OMPD_target_teams_distribute_simd: 2837 case OMPD_dispatch: 2838 case OMPD_masked: { 2839 // Special processing for flush and depobj clauses. 2840 Token ImplicitTok; 2841 bool ImplicitClauseAllowed = false; 2842 if (DKind == OMPD_flush || DKind == OMPD_depobj) { 2843 ImplicitTok = Tok; 2844 ImplicitClauseAllowed = true; 2845 } 2846 ConsumeToken(); 2847 // Parse directive name of the 'critical' directive if any. 2848 if (DKind == OMPD_critical) { 2849 BalancedDelimiterTracker T(*this, tok::l_paren, 2850 tok::annot_pragma_openmp_end); 2851 if (!T.consumeOpen()) { 2852 if (Tok.isAnyIdentifier()) { 2853 DirName = 2854 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 2855 ConsumeAnyToken(); 2856 } else { 2857 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 2858 } 2859 T.consumeClose(); 2860 } 2861 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 2862 CancelRegion = parseOpenMPDirectiveKind(*this); 2863 if (Tok.isNot(tok::annot_pragma_openmp_end)) 2864 ConsumeToken(); 2865 } 2866 2867 if (isOpenMPLoopDirective(DKind)) 2868 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 2869 if (isOpenMPSimdDirective(DKind)) 2870 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 2871 ParseScope OMPDirectiveScope(this, ScopeFlags); 2872 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 2873 2874 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2875 // If we are parsing for a directive within a metadirective, the directive 2876 // ends with a ')'. 2877 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) { 2878 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2879 ConsumeAnyToken(); 2880 break; 2881 } 2882 bool HasImplicitClause = false; 2883 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { 2884 HasImplicitClause = true; 2885 // Push copy of the current token back to stream to properly parse 2886 // pseudo-clause OMPFlushClause or OMPDepobjClause. 2887 PP.EnterToken(Tok, /*IsReinject*/ true); 2888 PP.EnterToken(ImplicitTok, /*IsReinject*/ true); 2889 ConsumeAnyToken(); 2890 } 2891 OpenMPClauseKind CKind = Tok.isAnnotation() 2892 ? OMPC_unknown 2893 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2894 if (HasImplicitClause) { 2895 assert(CKind == OMPC_unknown && "Must be unknown implicit clause."); 2896 if (DKind == OMPD_flush) { 2897 CKind = OMPC_flush; 2898 } else { 2899 assert(DKind == OMPD_depobj && 2900 "Expected flush or depobj directives."); 2901 CKind = OMPC_depobj; 2902 } 2903 } 2904 // No more implicit clauses allowed. 2905 ImplicitClauseAllowed = false; 2906 Actions.StartOpenMPClause(CKind); 2907 HasImplicitClause = false; 2908 OMPClause *Clause = ParseOpenMPClause( 2909 DKind, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2910 FirstClauses[unsigned(CKind)].setInt(true); 2911 if (Clause) { 2912 FirstClauses[unsigned(CKind)].setPointer(Clause); 2913 Clauses.push_back(Clause); 2914 } 2915 2916 // Skip ',' if any. 2917 if (Tok.is(tok::comma)) 2918 ConsumeToken(); 2919 Actions.EndOpenMPClause(); 2920 } 2921 // End location of the directive. 2922 EndLoc = Tok.getLocation(); 2923 // Consume final annot_pragma_openmp_end. 2924 ConsumeAnnotationToken(); 2925 2926 // OpenMP [2.13.8, ordered Construct, Syntax] 2927 // If the depend clause is specified, the ordered construct is a stand-alone 2928 // directive. 2929 if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) { 2930 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2931 ParsedStmtContext()) { 2932 Diag(Loc, diag::err_omp_immediate_directive) 2933 << getOpenMPDirectiveName(DKind) << 1 2934 << getOpenMPClauseName(OMPC_depend); 2935 } 2936 HasAssociatedStatement = false; 2937 } 2938 2939 if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) { 2940 Diag(Loc, diag::err_omp_required_clause) 2941 << getOpenMPDirectiveName(OMPD_tile) << "sizes"; 2942 } 2943 2944 StmtResult AssociatedStmt; 2945 if (HasAssociatedStatement) { 2946 // The body is a block scope like in Lambdas and Blocks. 2947 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2948 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 2949 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 2950 // should have at least one compound statement scope within it. 2951 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2952 { 2953 Sema::CompoundScopeRAII Scope(Actions); 2954 AssociatedStmt = ParseStatement(); 2955 2956 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) && 2957 getLangOpts().OpenMPIRBuilder) 2958 AssociatedStmt = Actions.ActOnOpenMPLoopnest(AssociatedStmt.get()); 2959 } 2960 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2961 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 2962 DKind == OMPD_target_exit_data) { 2963 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2964 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 2965 Actions.ActOnCompoundStmt(Loc, Loc, std::nullopt, 2966 /*isStmtExpr=*/false)); 2967 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2968 } 2969 Directive = Actions.ActOnOpenMPExecutableDirective( 2970 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 2971 EndLoc); 2972 2973 // Exit scope. 2974 Actions.EndOpenMPDSABlock(Directive.get()); 2975 OMPDirectiveScope.Exit(); 2976 break; 2977 } 2978 case OMPD_declare_simd: 2979 case OMPD_declare_target: 2980 case OMPD_begin_declare_target: 2981 case OMPD_end_declare_target: 2982 case OMPD_requires: 2983 case OMPD_begin_declare_variant: 2984 case OMPD_end_declare_variant: 2985 case OMPD_declare_variant: 2986 Diag(Tok, diag::err_omp_unexpected_directive) 2987 << 1 << getOpenMPDirectiveName(DKind); 2988 SkipUntil(tok::annot_pragma_openmp_end); 2989 break; 2990 case OMPD_unknown: 2991 default: 2992 Diag(Tok, diag::err_omp_unknown_directive); 2993 SkipUntil(tok::annot_pragma_openmp_end); 2994 break; 2995 } 2996 return Directive; 2997 } 2998 2999 // Parses simple list: 3000 // simple-variable-list: 3001 // '(' id-expression {, id-expression} ')' 3002 // 3003 bool Parser::ParseOpenMPSimpleVarList( 3004 OpenMPDirectiveKind Kind, 3005 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> 3006 &Callback, 3007 bool AllowScopeSpecifier) { 3008 // Parse '('. 3009 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3010 if (T.expectAndConsume(diag::err_expected_lparen_after, 3011 getOpenMPDirectiveName(Kind).data())) 3012 return true; 3013 bool IsCorrect = true; 3014 bool NoIdentIsFound = true; 3015 3016 // Read tokens while ')' or annot_pragma_openmp_end is not found. 3017 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 3018 CXXScopeSpec SS; 3019 UnqualifiedId Name; 3020 // Read var name. 3021 Token PrevTok = Tok; 3022 NoIdentIsFound = false; 3023 3024 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 3025 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 3026 /*ObjectHasErrors=*/false, false)) { 3027 IsCorrect = false; 3028 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3029 StopBeforeMatch); 3030 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, 3031 /*ObjectHadErrors=*/false, false, false, 3032 false, false, nullptr, Name)) { 3033 IsCorrect = false; 3034 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3035 StopBeforeMatch); 3036 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 3037 Tok.isNot(tok::annot_pragma_openmp_end)) { 3038 IsCorrect = false; 3039 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3040 StopBeforeMatch); 3041 Diag(PrevTok.getLocation(), diag::err_expected) 3042 << tok::identifier 3043 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 3044 } else { 3045 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 3046 } 3047 // Consume ','. 3048 if (Tok.is(tok::comma)) { 3049 ConsumeToken(); 3050 } 3051 } 3052 3053 if (NoIdentIsFound) { 3054 Diag(Tok, diag::err_expected) << tok::identifier; 3055 IsCorrect = false; 3056 } 3057 3058 // Parse ')'. 3059 IsCorrect = !T.consumeClose() && IsCorrect; 3060 3061 return !IsCorrect; 3062 } 3063 3064 OMPClause *Parser::ParseOpenMPSizesClause() { 3065 SourceLocation ClauseNameLoc = ConsumeToken(); 3066 SmallVector<Expr *, 4> ValExprs; 3067 3068 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3069 if (T.consumeOpen()) { 3070 Diag(Tok, diag::err_expected) << tok::l_paren; 3071 return nullptr; 3072 } 3073 3074 while (true) { 3075 ExprResult Val = ParseConstantExpression(); 3076 if (!Val.isUsable()) { 3077 T.skipToEnd(); 3078 return nullptr; 3079 } 3080 3081 ValExprs.push_back(Val.get()); 3082 3083 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end)) 3084 break; 3085 3086 ExpectAndConsume(tok::comma); 3087 } 3088 3089 T.consumeClose(); 3090 3091 return Actions.ActOnOpenMPSizesClause( 3092 ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation()); 3093 } 3094 3095 OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { 3096 SourceLocation Loc = Tok.getLocation(); 3097 ConsumeAnyToken(); 3098 3099 // Parse '('. 3100 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3101 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator")) 3102 return nullptr; 3103 SmallVector<Sema::UsesAllocatorsData, 4> Data; 3104 do { 3105 ExprResult Allocator = 3106 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression(); 3107 if (Allocator.isInvalid()) { 3108 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3109 StopBeforeMatch); 3110 break; 3111 } 3112 Sema::UsesAllocatorsData &D = Data.emplace_back(); 3113 D.Allocator = Allocator.get(); 3114 if (Tok.is(tok::l_paren)) { 3115 BalancedDelimiterTracker T(*this, tok::l_paren, 3116 tok::annot_pragma_openmp_end); 3117 T.consumeOpen(); 3118 ExprResult AllocatorTraits = 3119 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression(); 3120 T.consumeClose(); 3121 if (AllocatorTraits.isInvalid()) { 3122 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3123 StopBeforeMatch); 3124 break; 3125 } 3126 D.AllocatorTraits = AllocatorTraits.get(); 3127 D.LParenLoc = T.getOpenLocation(); 3128 D.RParenLoc = T.getCloseLocation(); 3129 } 3130 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 3131 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0; 3132 // Parse ',' 3133 if (Tok.is(tok::comma)) 3134 ConsumeAnyToken(); 3135 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); 3136 T.consumeClose(); 3137 return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(), 3138 T.getCloseLocation(), Data); 3139 } 3140 3141 /// Parsing of OpenMP clauses. 3142 /// 3143 /// clause: 3144 /// if-clause | final-clause | num_threads-clause | safelen-clause | 3145 /// default-clause | private-clause | firstprivate-clause | shared-clause 3146 /// | linear-clause | aligned-clause | collapse-clause | bind-clause | 3147 /// lastprivate-clause | reduction-clause | proc_bind-clause | 3148 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 3149 /// mergeable-clause | flush-clause | read-clause | write-clause | 3150 /// update-clause | capture-clause | seq_cst-clause | device-clause | 3151 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 3152 /// thread_limit-clause | priority-clause | grainsize-clause | 3153 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 3154 /// from-clause | is_device_ptr-clause | task_reduction-clause | 3155 /// in_reduction-clause | allocator-clause | allocate-clause | 3156 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | 3157 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause | 3158 /// exclusive-clause | uses_allocators-clause | use_device_addr-clause | 3159 /// has_device_addr 3160 /// 3161 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 3162 OpenMPClauseKind CKind, bool FirstClause) { 3163 OMPClauseKind = CKind; 3164 OMPClause *Clause = nullptr; 3165 bool ErrorFound = false; 3166 bool WrongDirective = false; 3167 // Check if clause is allowed for the given directive. 3168 if (CKind != OMPC_unknown && 3169 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 3170 Diag(Tok, diag::err_omp_unexpected_clause) 3171 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 3172 ErrorFound = true; 3173 WrongDirective = true; 3174 } 3175 3176 switch (CKind) { 3177 case OMPC_final: 3178 case OMPC_num_threads: 3179 case OMPC_safelen: 3180 case OMPC_simdlen: 3181 case OMPC_collapse: 3182 case OMPC_ordered: 3183 case OMPC_num_teams: 3184 case OMPC_thread_limit: 3185 case OMPC_priority: 3186 case OMPC_grainsize: 3187 case OMPC_num_tasks: 3188 case OMPC_hint: 3189 case OMPC_allocator: 3190 case OMPC_depobj: 3191 case OMPC_detach: 3192 case OMPC_novariants: 3193 case OMPC_nocontext: 3194 case OMPC_filter: 3195 case OMPC_partial: 3196 case OMPC_align: 3197 case OMPC_message: 3198 case OMPC_ompx_dyn_cgroup_mem: 3199 // OpenMP [2.5, Restrictions] 3200 // At most one num_threads clause can appear on the directive. 3201 // OpenMP [2.8.1, simd construct, Restrictions] 3202 // Only one safelen clause can appear on a simd directive. 3203 // Only one simdlen clause can appear on a simd directive. 3204 // Only one collapse clause can appear on a simd directive. 3205 // OpenMP [2.11.1, task Construct, Restrictions] 3206 // At most one if clause can appear on the directive. 3207 // At most one final clause can appear on the directive. 3208 // OpenMP [teams Construct, Restrictions] 3209 // At most one num_teams clause can appear on the directive. 3210 // At most one thread_limit clause can appear on the directive. 3211 // OpenMP [2.9.1, task Construct, Restrictions] 3212 // At most one priority clause can appear on the directive. 3213 // OpenMP [2.9.2, taskloop Construct, Restrictions] 3214 // At most one grainsize clause can appear on the directive. 3215 // OpenMP [2.9.2, taskloop Construct, Restrictions] 3216 // At most one num_tasks clause can appear on the directive. 3217 // OpenMP [2.11.3, allocate Directive, Restrictions] 3218 // At most one allocator clause can appear on the directive. 3219 // OpenMP 5.0, 2.10.1 task Construct, Restrictions. 3220 // At most one detach clause can appear on the directive. 3221 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions. 3222 // At most one novariants clause can appear on a dispatch directive. 3223 // At most one nocontext clause can appear on a dispatch directive. 3224 // OpenMP [5.1, error directive, Restrictions] 3225 // At most one message clause can appear on the directive 3226 if (!FirstClause) { 3227 Diag(Tok, diag::err_omp_more_one_clause) 3228 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3229 ErrorFound = true; 3230 } 3231 3232 if ((CKind == OMPC_ordered || CKind == OMPC_partial) && 3233 PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 3234 Clause = ParseOpenMPClause(CKind, WrongDirective); 3235 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks) 3236 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); 3237 else 3238 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 3239 break; 3240 case OMPC_default: 3241 case OMPC_proc_bind: 3242 case OMPC_atomic_default_mem_order: 3243 case OMPC_at: 3244 case OMPC_severity: 3245 case OMPC_bind: 3246 // OpenMP [2.14.3.1, Restrictions] 3247 // Only a single default clause may be specified on a parallel, task or 3248 // teams directive. 3249 // OpenMP [2.5, parallel Construct, Restrictions] 3250 // At most one proc_bind clause can appear on the directive. 3251 // OpenMP [5.0, Requires directive, Restrictions] 3252 // At most one atomic_default_mem_order clause can appear 3253 // on the directive 3254 // OpenMP [5.1, error directive, Restrictions] 3255 // At most one at clause can appear on the directive 3256 // At most one severity clause can appear on the directive 3257 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions. 3258 // At most one bind clause can appear on a loop directive. 3259 if (!FirstClause) { 3260 Diag(Tok, diag::err_omp_more_one_clause) 3261 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3262 ErrorFound = true; 3263 } 3264 3265 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 3266 break; 3267 case OMPC_device: 3268 case OMPC_schedule: 3269 case OMPC_dist_schedule: 3270 case OMPC_defaultmap: 3271 case OMPC_order: 3272 // OpenMP [2.7.1, Restrictions, p. 3] 3273 // Only one schedule clause can appear on a loop directive. 3274 // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 3275 // At most one defaultmap clause can appear on the directive. 3276 // OpenMP 5.0 [2.12.5, target construct, Restrictions] 3277 // At most one device clause can appear on the directive. 3278 // OpenMP 5.1 [2.11.3, order clause, Restrictions] 3279 // At most one order clause may appear on a construct. 3280 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 3281 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) { 3282 Diag(Tok, diag::err_omp_more_one_clause) 3283 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3284 ErrorFound = true; 3285 } 3286 [[fallthrough]]; 3287 case OMPC_if: 3288 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); 3289 break; 3290 case OMPC_nowait: 3291 case OMPC_untied: 3292 case OMPC_mergeable: 3293 case OMPC_read: 3294 case OMPC_write: 3295 case OMPC_capture: 3296 case OMPC_compare: 3297 case OMPC_seq_cst: 3298 case OMPC_acq_rel: 3299 case OMPC_acquire: 3300 case OMPC_release: 3301 case OMPC_relaxed: 3302 case OMPC_threads: 3303 case OMPC_simd: 3304 case OMPC_nogroup: 3305 case OMPC_unified_address: 3306 case OMPC_unified_shared_memory: 3307 case OMPC_reverse_offload: 3308 case OMPC_dynamic_allocators: 3309 case OMPC_full: 3310 // OpenMP [2.7.1, Restrictions, p. 9] 3311 // Only one ordered clause can appear on a loop directive. 3312 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 3313 // Only one nowait clause can appear on a for directive. 3314 // OpenMP [5.0, Requires directive, Restrictions] 3315 // Each of the requires clauses can appear at most once on the directive. 3316 if (!FirstClause) { 3317 Diag(Tok, diag::err_omp_more_one_clause) 3318 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3319 ErrorFound = true; 3320 } 3321 3322 Clause = ParseOpenMPClause(CKind, WrongDirective); 3323 break; 3324 case OMPC_update: 3325 if (!FirstClause) { 3326 Diag(Tok, diag::err_omp_more_one_clause) 3327 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3328 ErrorFound = true; 3329 } 3330 3331 Clause = (DKind == OMPD_depobj) 3332 ? ParseOpenMPSimpleClause(CKind, WrongDirective) 3333 : ParseOpenMPClause(CKind, WrongDirective); 3334 break; 3335 case OMPC_private: 3336 case OMPC_firstprivate: 3337 case OMPC_lastprivate: 3338 case OMPC_shared: 3339 case OMPC_reduction: 3340 case OMPC_task_reduction: 3341 case OMPC_in_reduction: 3342 case OMPC_linear: 3343 case OMPC_aligned: 3344 case OMPC_copyin: 3345 case OMPC_copyprivate: 3346 case OMPC_flush: 3347 case OMPC_depend: 3348 case OMPC_map: 3349 case OMPC_to: 3350 case OMPC_from: 3351 case OMPC_use_device_ptr: 3352 case OMPC_use_device_addr: 3353 case OMPC_is_device_ptr: 3354 case OMPC_has_device_addr: 3355 case OMPC_allocate: 3356 case OMPC_nontemporal: 3357 case OMPC_inclusive: 3358 case OMPC_exclusive: 3359 case OMPC_affinity: 3360 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 3361 break; 3362 case OMPC_sizes: 3363 if (!FirstClause) { 3364 Diag(Tok, diag::err_omp_more_one_clause) 3365 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3366 ErrorFound = true; 3367 } 3368 3369 Clause = ParseOpenMPSizesClause(); 3370 break; 3371 case OMPC_uses_allocators: 3372 Clause = ParseOpenMPUsesAllocatorClause(DKind); 3373 break; 3374 case OMPC_destroy: 3375 if (DKind != OMPD_interop) { 3376 if (!FirstClause) { 3377 Diag(Tok, diag::err_omp_more_one_clause) 3378 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3379 ErrorFound = true; 3380 } 3381 Clause = ParseOpenMPClause(CKind, WrongDirective); 3382 break; 3383 } 3384 [[fallthrough]]; 3385 case OMPC_init: 3386 case OMPC_use: 3387 Clause = ParseOpenMPInteropClause(CKind, WrongDirective); 3388 break; 3389 case OMPC_device_type: 3390 case OMPC_unknown: 3391 skipUntilPragmaOpenMPEnd(DKind); 3392 break; 3393 case OMPC_threadprivate: 3394 case OMPC_uniform: 3395 case OMPC_match: 3396 if (!WrongDirective) 3397 Diag(Tok, diag::err_omp_unexpected_clause) 3398 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 3399 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 3400 break; 3401 default: 3402 break; 3403 } 3404 return ErrorFound ? nullptr : Clause; 3405 } 3406 3407 /// Parses simple expression in parens for single-expression clauses of OpenMP 3408 /// constructs. 3409 /// \param RLoc Returned location of right paren. 3410 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 3411 SourceLocation &RLoc, 3412 bool IsAddressOfOperand) { 3413 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3414 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 3415 return ExprError(); 3416 3417 SourceLocation ELoc = Tok.getLocation(); 3418 ExprResult LHS( 3419 ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast)); 3420 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3421 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3422 3423 // Parse ')'. 3424 RLoc = Tok.getLocation(); 3425 if (!T.consumeClose()) 3426 RLoc = T.getCloseLocation(); 3427 3428 return Val; 3429 } 3430 3431 /// Parsing of OpenMP clauses with single expressions like 'final', 3432 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 3433 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or 3434 /// 'detach'. 3435 /// 3436 /// final-clause: 3437 /// 'final' '(' expression ')' 3438 /// 3439 /// num_threads-clause: 3440 /// 'num_threads' '(' expression ')' 3441 /// 3442 /// safelen-clause: 3443 /// 'safelen' '(' expression ')' 3444 /// 3445 /// simdlen-clause: 3446 /// 'simdlen' '(' expression ')' 3447 /// 3448 /// collapse-clause: 3449 /// 'collapse' '(' expression ')' 3450 /// 3451 /// priority-clause: 3452 /// 'priority' '(' expression ')' 3453 /// 3454 /// grainsize-clause: 3455 /// 'grainsize' '(' expression ')' 3456 /// 3457 /// num_tasks-clause: 3458 /// 'num_tasks' '(' expression ')' 3459 /// 3460 /// hint-clause: 3461 /// 'hint' '(' expression ')' 3462 /// 3463 /// allocator-clause: 3464 /// 'allocator' '(' expression ')' 3465 /// 3466 /// detach-clause: 3467 /// 'detach' '(' event-handler-expression ')' 3468 /// 3469 /// align-clause 3470 /// 'align' '(' positive-integer-constant ')' 3471 /// 3472 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 3473 bool ParseOnly) { 3474 SourceLocation Loc = ConsumeToken(); 3475 SourceLocation LLoc = Tok.getLocation(); 3476 SourceLocation RLoc; 3477 3478 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 3479 3480 if (Val.isInvalid()) 3481 return nullptr; 3482 3483 if (ParseOnly) 3484 return nullptr; 3485 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 3486 } 3487 3488 /// Parse indirect clause for '#pragma omp declare target' directive. 3489 /// 'indirect' '[' '(' invoked-by-fptr ')' ']' 3490 /// where invoked-by-fptr is a constant boolean expression that evaluates to 3491 /// true or false at compile time. 3492 bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI, 3493 bool ParseOnly) { 3494 SourceLocation Loc = ConsumeToken(); 3495 SourceLocation RLoc; 3496 3497 if (Tok.isNot(tok::l_paren)) { 3498 if (ParseOnly) 3499 return false; 3500 DTCI.Indirect = nullptr; 3501 return true; 3502 } 3503 3504 ExprResult Val = 3505 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc); 3506 if (Val.isInvalid()) 3507 return false; 3508 3509 if (ParseOnly) 3510 return false; 3511 3512 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() && 3513 !Val.get()->isInstantiationDependent() && 3514 !Val.get()->containsUnexpandedParameterPack()) { 3515 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get()); 3516 if (Ret.isInvalid()) 3517 return false; 3518 llvm::APSInt Result; 3519 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result, 3520 Sema::AllowFold); 3521 if (Ret.isInvalid()) 3522 return false; 3523 DTCI.Indirect = Val.get(); 3524 return true; 3525 } 3526 return false; 3527 } 3528 3529 /// Parses a comma-separated list of interop-types and a prefer_type list. 3530 /// 3531 bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo, 3532 OpenMPClauseKind Kind) { 3533 const Token &Tok = getCurToken(); 3534 bool HasError = false; 3535 bool IsTarget = false; 3536 bool IsTargetSync = false; 3537 3538 while (Tok.is(tok::identifier)) { 3539 // Currently prefer_type is only allowed with 'init' and it must be first. 3540 bool PreferTypeAllowed = Kind == OMPC_init && 3541 InteropInfo.PreferTypes.empty() && !IsTarget && 3542 !IsTargetSync; 3543 if (Tok.getIdentifierInfo()->isStr("target")) { 3544 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 3545 // Each interop-type may be specified on an action-clause at most 3546 // once. 3547 if (IsTarget) 3548 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target"; 3549 IsTarget = true; 3550 ConsumeToken(); 3551 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) { 3552 if (IsTargetSync) 3553 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync"; 3554 IsTargetSync = true; 3555 ConsumeToken(); 3556 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") && 3557 PreferTypeAllowed) { 3558 ConsumeToken(); 3559 BalancedDelimiterTracker PT(*this, tok::l_paren, 3560 tok::annot_pragma_openmp_end); 3561 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type")) 3562 HasError = true; 3563 3564 while (Tok.isNot(tok::r_paren)) { 3565 SourceLocation Loc = Tok.getLocation(); 3566 ExprResult LHS = ParseCastExpression(AnyCastExpr); 3567 ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr( 3568 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3569 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc, 3570 /*DiscardedValue=*/false); 3571 if (PTExpr.isUsable()) { 3572 InteropInfo.PreferTypes.push_back(PTExpr.get()); 3573 } else { 3574 HasError = true; 3575 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3576 StopBeforeMatch); 3577 } 3578 3579 if (Tok.is(tok::comma)) 3580 ConsumeToken(); 3581 } 3582 PT.consumeClose(); 3583 } else { 3584 HasError = true; 3585 Diag(Tok, diag::err_omp_expected_interop_type); 3586 ConsumeToken(); 3587 } 3588 if (!Tok.is(tok::comma)) 3589 break; 3590 ConsumeToken(); 3591 } 3592 3593 if (!HasError && !IsTarget && !IsTargetSync) { 3594 Diag(Tok, diag::err_omp_expected_interop_type); 3595 HasError = true; 3596 } 3597 3598 if (Kind == OMPC_init) { 3599 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync)) 3600 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types"; 3601 if (Tok.is(tok::colon)) 3602 ConsumeToken(); 3603 } 3604 3605 // As of OpenMP 5.1,there are two interop-types, "target" and 3606 // "targetsync". Either or both are allowed for a single interop. 3607 InteropInfo.IsTarget = IsTarget; 3608 InteropInfo.IsTargetSync = IsTargetSync; 3609 3610 return HasError; 3611 } 3612 3613 /// Parsing of OpenMP clauses that use an interop-var. 3614 /// 3615 /// init-clause: 3616 /// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var) 3617 /// 3618 /// destroy-clause: 3619 /// destroy(interop-var) 3620 /// 3621 /// use-clause: 3622 /// use(interop-var) 3623 /// 3624 /// interop-modifier: 3625 /// prefer_type(preference-list) 3626 /// 3627 /// preference-list: 3628 /// foreign-runtime-id [, foreign-runtime-id]... 3629 /// 3630 /// foreign-runtime-id: 3631 /// <string-literal> | <constant-integral-expression> 3632 /// 3633 /// interop-type: 3634 /// target | targetsync 3635 /// 3636 OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind, 3637 bool ParseOnly) { 3638 SourceLocation Loc = ConsumeToken(); 3639 // Parse '('. 3640 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3641 if (T.expectAndConsume(diag::err_expected_lparen_after, 3642 getOpenMPClauseName(Kind).data())) 3643 return nullptr; 3644 3645 bool InteropError = false; 3646 OMPInteropInfo InteropInfo; 3647 if (Kind == OMPC_init) 3648 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init); 3649 3650 // Parse the variable. 3651 SourceLocation VarLoc = Tok.getLocation(); 3652 ExprResult InteropVarExpr = 3653 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 3654 if (!InteropVarExpr.isUsable()) { 3655 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3656 StopBeforeMatch); 3657 } 3658 3659 // Parse ')'. 3660 SourceLocation RLoc = Tok.getLocation(); 3661 if (!T.consumeClose()) 3662 RLoc = T.getCloseLocation(); 3663 3664 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError) 3665 return nullptr; 3666 3667 if (Kind == OMPC_init) 3668 return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), InteropInfo, Loc, 3669 T.getOpenLocation(), VarLoc, RLoc); 3670 if (Kind == OMPC_use) 3671 return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc, 3672 T.getOpenLocation(), VarLoc, RLoc); 3673 3674 if (Kind == OMPC_destroy) 3675 return Actions.ActOnOpenMPDestroyClause(InteropVarExpr.get(), Loc, 3676 T.getOpenLocation(), VarLoc, RLoc); 3677 3678 llvm_unreachable("Unexpected interop variable clause."); 3679 } 3680 3681 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 3682 /// 3683 /// default-clause: 3684 /// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')' 3685 /// 3686 /// proc_bind-clause: 3687 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' 3688 /// 3689 /// bind-clause: 3690 /// 'bind' '(' 'teams' | 'parallel' | 'thread' ')' 3691 /// 3692 /// update-clause: 3693 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' | 3694 /// 'inoutset' ')' 3695 /// 3696 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 3697 bool ParseOnly) { 3698 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 3699 if (!Val || ParseOnly) 3700 return nullptr; 3701 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default && 3702 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private || 3703 static_cast<DefaultKind>(Val->Type) == 3704 OMP_DEFAULT_firstprivate)) { 3705 Diag(Val->LOpen, diag::err_omp_invalid_dsa) 3706 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) == 3707 OMP_DEFAULT_private 3708 ? OMPC_private 3709 : OMPC_firstprivate) 3710 << getOpenMPClauseName(OMPC_default) << "5.1"; 3711 return nullptr; 3712 } 3713 return Actions.ActOnOpenMPSimpleClause(Kind, Val->Type, 3714 Val->TypeLoc, Val->LOpen, 3715 Val->Loc, Val->RLoc); 3716 } 3717 3718 /// Parsing of OpenMP clauses like 'ordered'. 3719 /// 3720 /// ordered-clause: 3721 /// 'ordered' 3722 /// 3723 /// nowait-clause: 3724 /// 'nowait' 3725 /// 3726 /// untied-clause: 3727 /// 'untied' 3728 /// 3729 /// mergeable-clause: 3730 /// 'mergeable' 3731 /// 3732 /// read-clause: 3733 /// 'read' 3734 /// 3735 /// threads-clause: 3736 /// 'threads' 3737 /// 3738 /// simd-clause: 3739 /// 'simd' 3740 /// 3741 /// nogroup-clause: 3742 /// 'nogroup' 3743 /// 3744 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 3745 SourceLocation Loc = Tok.getLocation(); 3746 ConsumeAnyToken(); 3747 3748 if (ParseOnly) 3749 return nullptr; 3750 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 3751 } 3752 3753 /// Parsing of OpenMP clauses with single expressions and some additional 3754 /// argument like 'schedule' or 'dist_schedule'. 3755 /// 3756 /// schedule-clause: 3757 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 3758 /// ')' 3759 /// 3760 /// if-clause: 3761 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 3762 /// 3763 /// defaultmap: 3764 /// 'defaultmap' '(' modifier [ ':' kind ] ')' 3765 /// 3766 /// device-clause: 3767 /// 'device' '(' [ device-modifier ':' ] expression ')' 3768 /// 3769 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, 3770 OpenMPClauseKind Kind, 3771 bool ParseOnly) { 3772 SourceLocation Loc = ConsumeToken(); 3773 SourceLocation DelimLoc; 3774 // Parse '('. 3775 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3776 if (T.expectAndConsume(diag::err_expected_lparen_after, 3777 getOpenMPClauseName(Kind).data())) 3778 return nullptr; 3779 3780 ExprResult Val; 3781 SmallVector<unsigned, 4> Arg; 3782 SmallVector<SourceLocation, 4> KLoc; 3783 if (Kind == OMPC_schedule) { 3784 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 3785 Arg.resize(NumberOfElements); 3786 KLoc.resize(NumberOfElements); 3787 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 3788 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 3789 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 3790 unsigned KindModifier = getOpenMPSimpleClauseType( 3791 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3792 if (KindModifier > OMPC_SCHEDULE_unknown) { 3793 // Parse 'modifier' 3794 Arg[Modifier1] = KindModifier; 3795 KLoc[Modifier1] = Tok.getLocation(); 3796 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3797 Tok.isNot(tok::annot_pragma_openmp_end)) 3798 ConsumeAnyToken(); 3799 if (Tok.is(tok::comma)) { 3800 // Parse ',' 'modifier' 3801 ConsumeAnyToken(); 3802 KindModifier = getOpenMPSimpleClauseType( 3803 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3804 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 3805 ? KindModifier 3806 : (unsigned)OMPC_SCHEDULE_unknown; 3807 KLoc[Modifier2] = Tok.getLocation(); 3808 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3809 Tok.isNot(tok::annot_pragma_openmp_end)) 3810 ConsumeAnyToken(); 3811 } 3812 // Parse ':' 3813 if (Tok.is(tok::colon)) 3814 ConsumeAnyToken(); 3815 else 3816 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 3817 KindModifier = getOpenMPSimpleClauseType( 3818 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3819 } 3820 Arg[ScheduleKind] = KindModifier; 3821 KLoc[ScheduleKind] = Tok.getLocation(); 3822 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3823 Tok.isNot(tok::annot_pragma_openmp_end)) 3824 ConsumeAnyToken(); 3825 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 3826 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 3827 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 3828 Tok.is(tok::comma)) 3829 DelimLoc = ConsumeAnyToken(); 3830 } else if (Kind == OMPC_dist_schedule) { 3831 Arg.push_back(getOpenMPSimpleClauseType( 3832 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3833 KLoc.push_back(Tok.getLocation()); 3834 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3835 Tok.isNot(tok::annot_pragma_openmp_end)) 3836 ConsumeAnyToken(); 3837 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 3838 DelimLoc = ConsumeAnyToken(); 3839 } else if (Kind == OMPC_defaultmap) { 3840 // Get a defaultmap modifier 3841 unsigned Modifier = getOpenMPSimpleClauseType( 3842 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3843 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 3844 // pointer 3845 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 3846 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 3847 Arg.push_back(Modifier); 3848 KLoc.push_back(Tok.getLocation()); 3849 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3850 Tok.isNot(tok::annot_pragma_openmp_end)) 3851 ConsumeAnyToken(); 3852 // Parse ':' 3853 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) { 3854 if (Tok.is(tok::colon)) 3855 ConsumeAnyToken(); 3856 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 3857 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 3858 // Get a defaultmap kind 3859 Arg.push_back(getOpenMPSimpleClauseType( 3860 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3861 KLoc.push_back(Tok.getLocation()); 3862 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3863 Tok.isNot(tok::annot_pragma_openmp_end)) 3864 ConsumeAnyToken(); 3865 } else { 3866 Arg.push_back(OMPC_DEFAULTMAP_unknown); 3867 KLoc.push_back(SourceLocation()); 3868 } 3869 } else if (Kind == OMPC_order) { 3870 enum { Modifier, OrderKind, NumberOfElements }; 3871 Arg.resize(NumberOfElements); 3872 KLoc.resize(NumberOfElements); 3873 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown; 3874 Arg[OrderKind] = OMPC_ORDER_unknown; 3875 unsigned KindModifier = getOpenMPSimpleClauseType( 3876 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3877 if (KindModifier > OMPC_ORDER_unknown) { 3878 // Parse 'modifier' 3879 Arg[Modifier] = KindModifier; 3880 KLoc[Modifier] = Tok.getLocation(); 3881 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3882 Tok.isNot(tok::annot_pragma_openmp_end)) 3883 ConsumeAnyToken(); 3884 // Parse ':' 3885 if (Tok.is(tok::colon)) 3886 ConsumeAnyToken(); 3887 else 3888 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier"; 3889 KindModifier = getOpenMPSimpleClauseType( 3890 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3891 } 3892 Arg[OrderKind] = KindModifier; 3893 KLoc[OrderKind] = Tok.getLocation(); 3894 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3895 Tok.isNot(tok::annot_pragma_openmp_end)) 3896 ConsumeAnyToken(); 3897 } else if (Kind == OMPC_device) { 3898 // Only target executable directives support extended device construct. 3899 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 && 3900 NextToken().is(tok::colon)) { 3901 // Parse optional <device modifier> ':' 3902 Arg.push_back(getOpenMPSimpleClauseType( 3903 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3904 KLoc.push_back(Tok.getLocation()); 3905 ConsumeAnyToken(); 3906 // Parse ':' 3907 ConsumeAnyToken(); 3908 } else { 3909 Arg.push_back(OMPC_DEVICE_unknown); 3910 KLoc.emplace_back(); 3911 } 3912 } else if (Kind == OMPC_grainsize) { 3913 // Parse optional <grainsize modifier> ':' 3914 OpenMPGrainsizeClauseModifier Modifier = 3915 static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType( 3916 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 3917 getLangOpts())); 3918 if (getLangOpts().OpenMP >= 51) { 3919 if (NextToken().is(tok::colon)) { 3920 Arg.push_back(Modifier); 3921 KLoc.push_back(Tok.getLocation()); 3922 // Parse modifier 3923 ConsumeAnyToken(); 3924 // Parse ':' 3925 ConsumeAnyToken(); 3926 } else { 3927 if (Modifier == OMPC_GRAINSIZE_strict) { 3928 Diag(Tok, diag::err_modifier_expected_colon) << "strict"; 3929 // Parse modifier 3930 ConsumeAnyToken(); 3931 } 3932 Arg.push_back(OMPC_GRAINSIZE_unknown); 3933 KLoc.emplace_back(); 3934 } 3935 } else { 3936 Arg.push_back(OMPC_GRAINSIZE_unknown); 3937 KLoc.emplace_back(); 3938 } 3939 } else if (Kind == OMPC_num_tasks) { 3940 // Parse optional <num_tasks modifier> ':' 3941 OpenMPNumTasksClauseModifier Modifier = 3942 static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType( 3943 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), 3944 getLangOpts())); 3945 if (getLangOpts().OpenMP >= 51) { 3946 if (NextToken().is(tok::colon)) { 3947 Arg.push_back(Modifier); 3948 KLoc.push_back(Tok.getLocation()); 3949 // Parse modifier 3950 ConsumeAnyToken(); 3951 // Parse ':' 3952 ConsumeAnyToken(); 3953 } else { 3954 if (Modifier == OMPC_NUMTASKS_strict) { 3955 Diag(Tok, diag::err_modifier_expected_colon) << "strict"; 3956 // Parse modifier 3957 ConsumeAnyToken(); 3958 } 3959 Arg.push_back(OMPC_NUMTASKS_unknown); 3960 KLoc.emplace_back(); 3961 } 3962 } else { 3963 Arg.push_back(OMPC_NUMTASKS_unknown); 3964 KLoc.emplace_back(); 3965 } 3966 } else { 3967 assert(Kind == OMPC_if); 3968 KLoc.push_back(Tok.getLocation()); 3969 TentativeParsingAction TPA(*this); 3970 auto DK = parseOpenMPDirectiveKind(*this); 3971 Arg.push_back(DK); 3972 if (DK != OMPD_unknown) { 3973 ConsumeToken(); 3974 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 3975 TPA.Commit(); 3976 DelimLoc = ConsumeToken(); 3977 } else { 3978 TPA.Revert(); 3979 Arg.back() = unsigned(OMPD_unknown); 3980 } 3981 } else { 3982 TPA.Revert(); 3983 } 3984 } 3985 3986 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 3987 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 3988 Kind == OMPC_if || Kind == OMPC_device || 3989 Kind == OMPC_grainsize || Kind == OMPC_num_tasks; 3990 if (NeedAnExpression) { 3991 SourceLocation ELoc = Tok.getLocation(); 3992 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 3993 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 3994 Val = 3995 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3996 } 3997 3998 // Parse ')'. 3999 SourceLocation RLoc = Tok.getLocation(); 4000 if (!T.consumeClose()) 4001 RLoc = T.getCloseLocation(); 4002 4003 if (NeedAnExpression && Val.isInvalid()) 4004 return nullptr; 4005 4006 if (ParseOnly) 4007 return nullptr; 4008 return Actions.ActOnOpenMPSingleExprWithArgClause( 4009 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 4010 } 4011 4012 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 4013 UnqualifiedId &ReductionId) { 4014 if (ReductionIdScopeSpec.isEmpty()) { 4015 auto OOK = OO_None; 4016 switch (P.getCurToken().getKind()) { 4017 case tok::plus: 4018 OOK = OO_Plus; 4019 break; 4020 case tok::minus: 4021 OOK = OO_Minus; 4022 break; 4023 case tok::star: 4024 OOK = OO_Star; 4025 break; 4026 case tok::amp: 4027 OOK = OO_Amp; 4028 break; 4029 case tok::pipe: 4030 OOK = OO_Pipe; 4031 break; 4032 case tok::caret: 4033 OOK = OO_Caret; 4034 break; 4035 case tok::ampamp: 4036 OOK = OO_AmpAmp; 4037 break; 4038 case tok::pipepipe: 4039 OOK = OO_PipePipe; 4040 break; 4041 default: 4042 break; 4043 } 4044 if (OOK != OO_None) { 4045 SourceLocation OpLoc = P.ConsumeToken(); 4046 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 4047 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 4048 return false; 4049 } 4050 } 4051 return P.ParseUnqualifiedId( 4052 ReductionIdScopeSpec, /*ObjectType=*/nullptr, 4053 /*ObjectHadErrors=*/false, /*EnteringContext*/ false, 4054 /*AllowDestructorName*/ false, 4055 /*AllowConstructorName*/ false, 4056 /*AllowDeductionGuide*/ false, nullptr, ReductionId); 4057 } 4058 4059 /// Checks if the token is a valid map-type-modifier. 4060 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses. 4061 static OpenMPMapModifierKind isMapModifier(Parser &P) { 4062 Token Tok = P.getCurToken(); 4063 if (!Tok.is(tok::identifier)) 4064 return OMPC_MAP_MODIFIER_unknown; 4065 4066 Preprocessor &PP = P.getPreprocessor(); 4067 OpenMPMapModifierKind TypeModifier = 4068 static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType( 4069 OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); 4070 return TypeModifier; 4071 } 4072 4073 /// Parse the mapper modifier in map, to, and from clauses. 4074 bool Parser::parseMapperModifier(Sema::OpenMPVarListDataTy &Data) { 4075 // Parse '('. 4076 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 4077 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 4078 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4079 StopBeforeMatch); 4080 return true; 4081 } 4082 // Parse mapper-identifier 4083 if (getLangOpts().CPlusPlus) 4084 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 4085 /*ObjectType=*/nullptr, 4086 /*ObjectHasErrors=*/false, 4087 /*EnteringContext=*/false); 4088 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 4089 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 4090 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4091 StopBeforeMatch); 4092 return true; 4093 } 4094 auto &DeclNames = Actions.getASTContext().DeclarationNames; 4095 Data.ReductionOrMapperId = DeclarationNameInfo( 4096 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 4097 ConsumeToken(); 4098 // Parse ')'. 4099 return T.consumeClose(); 4100 } 4101 4102 /// Parse map-type-modifiers in map clause. 4103 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 4104 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) | 4105 /// present 4106 bool Parser::parseMapTypeModifiers(Sema::OpenMPVarListDataTy &Data) { 4107 while (getCurToken().isNot(tok::colon)) { 4108 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 4109 if (TypeModifier == OMPC_MAP_MODIFIER_always || 4110 TypeModifier == OMPC_MAP_MODIFIER_close || 4111 TypeModifier == OMPC_MAP_MODIFIER_present || 4112 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) { 4113 Data.MapTypeModifiers.push_back(TypeModifier); 4114 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 4115 ConsumeToken(); 4116 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 4117 Data.MapTypeModifiers.push_back(TypeModifier); 4118 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 4119 ConsumeToken(); 4120 if (parseMapperModifier(Data)) 4121 return true; 4122 } else { 4123 // For the case of unknown map-type-modifier or a map-type. 4124 // Map-type is followed by a colon; the function returns when it 4125 // encounters a token followed by a colon. 4126 if (Tok.is(tok::comma)) { 4127 Diag(Tok, diag::err_omp_map_type_modifier_missing); 4128 ConsumeToken(); 4129 continue; 4130 } 4131 // Potential map-type token as it is followed by a colon. 4132 if (PP.LookAhead(0).is(tok::colon)) 4133 return false; 4134 Diag(Tok, diag::err_omp_unknown_map_type_modifier) 4135 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1) 4136 : 0) 4137 << getLangOpts().OpenMPExtensions; 4138 ConsumeToken(); 4139 } 4140 if (getCurToken().is(tok::comma)) 4141 ConsumeToken(); 4142 } 4143 return false; 4144 } 4145 4146 /// Checks if the token is a valid map-type. 4147 /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses. 4148 static OpenMPMapClauseKind isMapType(Parser &P) { 4149 Token Tok = P.getCurToken(); 4150 // The map-type token can be either an identifier or the C++ delete keyword. 4151 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 4152 return OMPC_MAP_unknown; 4153 Preprocessor &PP = P.getPreprocessor(); 4154 OpenMPMapClauseKind MapType = 4155 static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 4156 OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); 4157 return MapType; 4158 } 4159 4160 /// Parse map-type in map clause. 4161 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 4162 /// where, map-type ::= to | from | tofrom | alloc | release | delete 4163 static void parseMapType(Parser &P, Sema::OpenMPVarListDataTy &Data) { 4164 Token Tok = P.getCurToken(); 4165 if (Tok.is(tok::colon)) { 4166 P.Diag(Tok, diag::err_omp_map_type_missing); 4167 return; 4168 } 4169 Data.ExtraModifier = isMapType(P); 4170 if (Data.ExtraModifier == OMPC_MAP_unknown) 4171 P.Diag(Tok, diag::err_omp_unknown_map_type); 4172 P.ConsumeToken(); 4173 } 4174 4175 /// Parses simple expression in parens for single-expression clauses of OpenMP 4176 /// constructs. 4177 ExprResult Parser::ParseOpenMPIteratorsExpr() { 4178 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" && 4179 "Expected 'iterator' token."); 4180 SourceLocation IteratorKwLoc = ConsumeToken(); 4181 4182 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 4183 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator")) 4184 return ExprError(); 4185 4186 SourceLocation LLoc = T.getOpenLocation(); 4187 SmallVector<Sema::OMPIteratorData, 4> Data; 4188 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 4189 // Check if the type parsing is required. 4190 ParsedType IteratorType; 4191 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) { 4192 // identifier '=' is not found - parse type. 4193 TypeResult TR = ParseTypeName(); 4194 if (TR.isInvalid()) { 4195 T.skipToEnd(); 4196 return ExprError(); 4197 } 4198 IteratorType = TR.get(); 4199 } 4200 4201 // Parse identifier. 4202 IdentifierInfo *II = nullptr; 4203 SourceLocation IdLoc; 4204 if (Tok.is(tok::identifier)) { 4205 II = Tok.getIdentifierInfo(); 4206 IdLoc = ConsumeToken(); 4207 } else { 4208 Diag(Tok, diag::err_expected_unqualified_id) << 0; 4209 } 4210 4211 // Parse '='. 4212 SourceLocation AssignLoc; 4213 if (Tok.is(tok::equal)) 4214 AssignLoc = ConsumeToken(); 4215 else 4216 Diag(Tok, diag::err_omp_expected_equal_in_iterator); 4217 4218 // Parse range-specification - <begin> ':' <end> [ ':' <step> ] 4219 ColonProtectionRAIIObject ColonRAII(*this); 4220 // Parse <begin> 4221 SourceLocation Loc = Tok.getLocation(); 4222 ExprResult LHS = ParseCastExpression(AnyCastExpr); 4223 ExprResult Begin = Actions.CorrectDelayedTyposInExpr( 4224 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4225 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc, 4226 /*DiscardedValue=*/false); 4227 // Parse ':'. 4228 SourceLocation ColonLoc; 4229 if (Tok.is(tok::colon)) 4230 ColonLoc = ConsumeToken(); 4231 4232 // Parse <end> 4233 Loc = Tok.getLocation(); 4234 LHS = ParseCastExpression(AnyCastExpr); 4235 ExprResult End = Actions.CorrectDelayedTyposInExpr( 4236 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4237 End = Actions.ActOnFinishFullExpr(End.get(), Loc, 4238 /*DiscardedValue=*/false); 4239 4240 SourceLocation SecColonLoc; 4241 ExprResult Step; 4242 // Parse optional step. 4243 if (Tok.is(tok::colon)) { 4244 // Parse ':' 4245 SecColonLoc = ConsumeToken(); 4246 // Parse <step> 4247 Loc = Tok.getLocation(); 4248 LHS = ParseCastExpression(AnyCastExpr); 4249 Step = Actions.CorrectDelayedTyposInExpr( 4250 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4251 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc, 4252 /*DiscardedValue=*/false); 4253 } 4254 4255 // Parse ',' or ')' 4256 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 4257 Diag(Tok, diag::err_omp_expected_punc_after_iterator); 4258 if (Tok.is(tok::comma)) 4259 ConsumeToken(); 4260 4261 Sema::OMPIteratorData &D = Data.emplace_back(); 4262 D.DeclIdent = II; 4263 D.DeclIdentLoc = IdLoc; 4264 D.Type = IteratorType; 4265 D.AssignLoc = AssignLoc; 4266 D.ColonLoc = ColonLoc; 4267 D.SecColonLoc = SecColonLoc; 4268 D.Range.Begin = Begin.get(); 4269 D.Range.End = End.get(); 4270 D.Range.Step = Step.get(); 4271 } 4272 4273 // Parse ')'. 4274 SourceLocation RLoc = Tok.getLocation(); 4275 if (!T.consumeClose()) 4276 RLoc = T.getCloseLocation(); 4277 4278 return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc, 4279 Data); 4280 } 4281 4282 bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind, 4283 Sema::OpenMPVarListDataTy &Data, 4284 const LangOptions &LangOpts) { 4285 // Currently the only reserved locator is 'omp_all_memory' which is only 4286 // allowed on a depend clause. 4287 if (Kind != OMPC_depend || LangOpts.OpenMP < 51) 4288 return false; 4289 4290 if (Tok.is(tok::identifier) && 4291 Tok.getIdentifierInfo()->isStr("omp_all_memory")) { 4292 4293 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory || 4294 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory) 4295 Diag(Tok, diag::warn_omp_more_one_omp_all_memory); 4296 else if (Data.ExtraModifier != OMPC_DEPEND_out && 4297 Data.ExtraModifier != OMPC_DEPEND_inout) 4298 Diag(Tok, diag::err_omp_requires_out_inout_depend_type); 4299 else 4300 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out 4301 ? OMPC_DEPEND_outallmemory 4302 : OMPC_DEPEND_inoutallmemory; 4303 ConsumeToken(); 4304 return true; 4305 } 4306 return false; 4307 } 4308 4309 /// Parses clauses with list. 4310 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 4311 OpenMPClauseKind Kind, 4312 SmallVectorImpl<Expr *> &Vars, 4313 Sema::OpenMPVarListDataTy &Data) { 4314 UnqualifiedId UnqualifiedReductionId; 4315 bool InvalidReductionId = false; 4316 bool IsInvalidMapperModifier = false; 4317 4318 // Parse '('. 4319 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 4320 if (T.expectAndConsume(diag::err_expected_lparen_after, 4321 getOpenMPClauseName(Kind).data())) 4322 return true; 4323 4324 bool HasIterator = false; 4325 bool InvalidIterator = false; 4326 bool NeedRParenForLinear = false; 4327 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 4328 tok::annot_pragma_openmp_end); 4329 // Handle reduction-identifier for reduction clause. 4330 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 4331 Kind == OMPC_in_reduction) { 4332 Data.ExtraModifier = OMPC_REDUCTION_unknown; 4333 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 && 4334 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) && 4335 NextToken().is(tok::comma)) { 4336 // Parse optional reduction modifier. 4337 Data.ExtraModifier = 4338 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4339 Data.ExtraModifierLoc = Tok.getLocation(); 4340 ConsumeToken(); 4341 assert(Tok.is(tok::comma) && "Expected comma."); 4342 (void)ConsumeToken(); 4343 } 4344 ColonProtectionRAIIObject ColonRAII(*this); 4345 if (getLangOpts().CPlusPlus) 4346 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 4347 /*ObjectType=*/nullptr, 4348 /*ObjectHasErrors=*/false, 4349 /*EnteringContext=*/false); 4350 InvalidReductionId = ParseReductionId( 4351 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 4352 if (InvalidReductionId) { 4353 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4354 StopBeforeMatch); 4355 } 4356 if (Tok.is(tok::colon)) 4357 Data.ColonLoc = ConsumeToken(); 4358 else 4359 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 4360 if (!InvalidReductionId) 4361 Data.ReductionOrMapperId = 4362 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 4363 } else if (Kind == OMPC_depend) { 4364 if (getLangOpts().OpenMP >= 50) { 4365 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { 4366 // Handle optional dependence modifier. 4367 // iterator(iterators-definition) 4368 // where iterators-definition is iterator-specifier [, 4369 // iterators-definition ] 4370 // where iterator-specifier is [ iterator-type ] identifier = 4371 // range-specification 4372 HasIterator = true; 4373 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 4374 ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); 4375 Data.DepModOrTailExpr = IteratorRes.get(); 4376 // Parse ',' 4377 ExpectAndConsume(tok::comma); 4378 } 4379 } 4380 // Handle dependency type for depend clause. 4381 ColonProtectionRAIIObject ColonRAII(*this); 4382 Data.ExtraModifier = getOpenMPSimpleClauseType( 4383 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 4384 getLangOpts()); 4385 Data.ExtraModifierLoc = Tok.getLocation(); 4386 if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 4387 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4388 StopBeforeMatch); 4389 } else { 4390 ConsumeToken(); 4391 // Special processing for depend(source) clause. 4392 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 4393 // Parse ')'. 4394 T.consumeClose(); 4395 return false; 4396 } 4397 } 4398 if (Tok.is(tok::colon)) { 4399 Data.ColonLoc = ConsumeToken(); 4400 } else { 4401 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 4402 : diag::warn_pragma_expected_colon) 4403 << "dependency type"; 4404 } 4405 } else if (Kind == OMPC_linear) { 4406 // Try to parse modifier if any. 4407 Data.ExtraModifier = OMPC_LINEAR_val; 4408 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 4409 Data.ExtraModifier = 4410 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4411 Data.ExtraModifierLoc = ConsumeToken(); 4412 LinearT.consumeOpen(); 4413 NeedRParenForLinear = true; 4414 } 4415 } else if (Kind == OMPC_lastprivate) { 4416 // Try to parse modifier if any. 4417 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 4418 // Conditional modifier allowed only in OpenMP 5.0 and not supported in 4419 // distribute and taskloop based directives. 4420 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 4421 !isOpenMPTaskLoopDirective(DKind)) && 4422 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 4423 Data.ExtraModifier = 4424 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4425 Data.ExtraModifierLoc = Tok.getLocation(); 4426 ConsumeToken(); 4427 assert(Tok.is(tok::colon) && "Expected colon."); 4428 Data.ColonLoc = ConsumeToken(); 4429 } 4430 } else if (Kind == OMPC_map) { 4431 // Handle optional iterator map modifier. 4432 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { 4433 HasIterator = true; 4434 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 4435 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator); 4436 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 4437 ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); 4438 Data.IteratorExpr = IteratorRes.get(); 4439 // Parse ',' 4440 ExpectAndConsume(tok::comma); 4441 if (getLangOpts().OpenMP < 52) { 4442 Diag(Tok, diag::err_omp_unknown_map_type_modifier) 4443 << (getLangOpts().OpenMP >= 51 ? 1 : 0) 4444 << getLangOpts().OpenMPExtensions; 4445 InvalidIterator = true; 4446 } 4447 } 4448 // Handle map type for map clause. 4449 ColonProtectionRAIIObject ColonRAII(*this); 4450 4451 // The first identifier may be a list item, a map-type or a 4452 // map-type-modifier. The map-type can also be delete which has the same 4453 // spelling of the C++ delete keyword. 4454 Data.ExtraModifier = OMPC_MAP_unknown; 4455 Data.ExtraModifierLoc = Tok.getLocation(); 4456 4457 // Check for presence of a colon in the map clause. 4458 TentativeParsingAction TPA(*this); 4459 bool ColonPresent = false; 4460 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4461 StopBeforeMatch)) { 4462 if (Tok.is(tok::colon)) 4463 ColonPresent = true; 4464 } 4465 TPA.Revert(); 4466 // Only parse map-type-modifier[s] and map-type if a colon is present in 4467 // the map clause. 4468 if (ColonPresent) { 4469 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 4470 if (!IsInvalidMapperModifier) 4471 parseMapType(*this, Data); 4472 else 4473 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 4474 } 4475 if (Data.ExtraModifier == OMPC_MAP_unknown) { 4476 Data.ExtraModifier = OMPC_MAP_tofrom; 4477 if (getLangOpts().OpenMP >= 52) { 4478 if (DKind == OMPD_target_enter_data) 4479 Data.ExtraModifier = OMPC_MAP_to; 4480 else if (DKind == OMPD_target_exit_data) 4481 Data.ExtraModifier = OMPC_MAP_from; 4482 } 4483 Data.IsMapTypeImplicit = true; 4484 } 4485 4486 if (Tok.is(tok::colon)) 4487 Data.ColonLoc = ConsumeToken(); 4488 } else if (Kind == OMPC_to || Kind == OMPC_from) { 4489 while (Tok.is(tok::identifier)) { 4490 auto Modifier = static_cast<OpenMPMotionModifierKind>( 4491 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts())); 4492 if (Modifier == OMPC_MOTION_MODIFIER_unknown) 4493 break; 4494 Data.MotionModifiers.push_back(Modifier); 4495 Data.MotionModifiersLoc.push_back(Tok.getLocation()); 4496 ConsumeToken(); 4497 if (Modifier == OMPC_MOTION_MODIFIER_mapper) { 4498 IsInvalidMapperModifier = parseMapperModifier(Data); 4499 if (IsInvalidMapperModifier) 4500 break; 4501 } 4502 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers. 4503 if (getLangOpts().OpenMP < 51) 4504 break; 4505 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'. 4506 // TODO: Is that intentional? 4507 if (Tok.is(tok::comma)) 4508 ConsumeToken(); 4509 } 4510 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) { 4511 if (!IsInvalidMapperModifier) { 4512 if (getLangOpts().OpenMP < 51) 4513 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 4514 else 4515 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier"; 4516 } 4517 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4518 StopBeforeMatch); 4519 } 4520 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is 4521 // that intentional? 4522 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) && 4523 Tok.is(tok::colon)) 4524 Data.ColonLoc = ConsumeToken(); 4525 } else if (Kind == OMPC_allocate || 4526 (Kind == OMPC_affinity && Tok.is(tok::identifier) && 4527 PP.getSpelling(Tok) == "iterator")) { 4528 // Handle optional allocator expression followed by colon delimiter. 4529 ColonProtectionRAIIObject ColonRAII(*this); 4530 TentativeParsingAction TPA(*this); 4531 // OpenMP 5.0, 2.10.1, task Construct. 4532 // where aff-modifier is one of the following: 4533 // iterator(iterators-definition) 4534 ExprResult Tail; 4535 if (Kind == OMPC_allocate) { 4536 Tail = ParseAssignmentExpression(); 4537 } else { 4538 HasIterator = true; 4539 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 4540 Tail = ParseOpenMPIteratorsExpr(); 4541 } 4542 Tail = Actions.CorrectDelayedTyposInExpr(Tail); 4543 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 4544 /*DiscardedValue=*/false); 4545 if (Tail.isUsable()) { 4546 if (Tok.is(tok::colon)) { 4547 Data.DepModOrTailExpr = Tail.get(); 4548 Data.ColonLoc = ConsumeToken(); 4549 TPA.Commit(); 4550 } else { 4551 // Colon not found, parse only list of variables. 4552 TPA.Revert(); 4553 } 4554 } else { 4555 // Parsing was unsuccessfull, revert and skip to the end of clause or 4556 // directive. 4557 TPA.Revert(); 4558 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4559 StopBeforeMatch); 4560 } 4561 } else if (Kind == OMPC_adjust_args) { 4562 // Handle adjust-op for adjust_args clause. 4563 ColonProtectionRAIIObject ColonRAII(*this); 4564 Data.ExtraModifier = getOpenMPSimpleClauseType( 4565 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 4566 getLangOpts()); 4567 Data.ExtraModifierLoc = Tok.getLocation(); 4568 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) { 4569 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4570 StopBeforeMatch); 4571 } else { 4572 ConsumeToken(); 4573 if (Tok.is(tok::colon)) 4574 Data.ColonLoc = Tok.getLocation(); 4575 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon, 4576 "adjust-op"); 4577 } 4578 } 4579 4580 bool IsComma = 4581 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 4582 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 4583 (Kind == OMPC_reduction && !InvalidReductionId) || 4584 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 4585 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) || 4586 (Kind == OMPC_adjust_args && 4587 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown); 4588 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 4589 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 4590 Tok.isNot(tok::annot_pragma_openmp_end))) { 4591 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); 4592 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 4593 if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) { 4594 // Parse variable 4595 ExprResult VarExpr = 4596 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 4597 if (VarExpr.isUsable()) { 4598 Vars.push_back(VarExpr.get()); 4599 } else { 4600 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4601 StopBeforeMatch); 4602 } 4603 } 4604 // Skip ',' if any 4605 IsComma = Tok.is(tok::comma); 4606 if (IsComma) 4607 ConsumeToken(); 4608 else if (Tok.isNot(tok::r_paren) && 4609 Tok.isNot(tok::annot_pragma_openmp_end) && 4610 (!MayHaveTail || Tok.isNot(tok::colon))) 4611 Diag(Tok, diag::err_omp_expected_punc) 4612 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 4613 : getOpenMPClauseName(Kind)) 4614 << (Kind == OMPC_flush); 4615 } 4616 4617 // Parse ')' for linear clause with modifier. 4618 if (NeedRParenForLinear) 4619 LinearT.consumeClose(); 4620 4621 // Parse ':' linear-step (or ':' alignment). 4622 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 4623 if (MustHaveTail) { 4624 Data.ColonLoc = Tok.getLocation(); 4625 SourceLocation ELoc = ConsumeToken(); 4626 ExprResult Tail = ParseAssignmentExpression(); 4627 Tail = 4628 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 4629 if (Tail.isUsable()) 4630 Data.DepModOrTailExpr = Tail.get(); 4631 else 4632 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4633 StopBeforeMatch); 4634 } 4635 4636 // Parse ')'. 4637 Data.RLoc = Tok.getLocation(); 4638 if (!T.consumeClose()) 4639 Data.RLoc = T.getCloseLocation(); 4640 // Exit from scope when the iterator is used in depend clause. 4641 if (HasIterator) 4642 ExitScope(); 4643 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 4644 (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || 4645 IsInvalidMapperModifier || InvalidIterator; 4646 } 4647 4648 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 4649 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction', 4650 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'. 4651 /// 4652 /// private-clause: 4653 /// 'private' '(' list ')' 4654 /// firstprivate-clause: 4655 /// 'firstprivate' '(' list ')' 4656 /// lastprivate-clause: 4657 /// 'lastprivate' '(' list ')' 4658 /// shared-clause: 4659 /// 'shared' '(' list ')' 4660 /// linear-clause: 4661 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 4662 /// aligned-clause: 4663 /// 'aligned' '(' list [ ':' alignment ] ')' 4664 /// reduction-clause: 4665 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')' 4666 /// task_reduction-clause: 4667 /// 'task_reduction' '(' reduction-identifier ':' list ')' 4668 /// in_reduction-clause: 4669 /// 'in_reduction' '(' reduction-identifier ':' list ')' 4670 /// copyprivate-clause: 4671 /// 'copyprivate' '(' list ')' 4672 /// flush-clause: 4673 /// 'flush' '(' list ')' 4674 /// depend-clause: 4675 /// 'depend' '(' in | out | inout : list | source ')' 4676 /// map-clause: 4677 /// 'map' '(' [ [ always [,] ] [ close [,] ] 4678 /// [ mapper '(' mapper-identifier ')' [,] ] 4679 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 4680 /// to-clause: 4681 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 4682 /// from-clause: 4683 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 4684 /// use_device_ptr-clause: 4685 /// 'use_device_ptr' '(' list ')' 4686 /// use_device_addr-clause: 4687 /// 'use_device_addr' '(' list ')' 4688 /// is_device_ptr-clause: 4689 /// 'is_device_ptr' '(' list ')' 4690 /// has_device_addr-clause: 4691 /// 'has_device_addr' '(' list ')' 4692 /// allocate-clause: 4693 /// 'allocate' '(' [ allocator ':' ] list ')' 4694 /// nontemporal-clause: 4695 /// 'nontemporal' '(' list ')' 4696 /// inclusive-clause: 4697 /// 'inclusive' '(' list ')' 4698 /// exclusive-clause: 4699 /// 'exclusive' '(' list ')' 4700 /// 4701 /// For 'linear' clause linear-list may have the following forms: 4702 /// list 4703 /// modifier(list) 4704 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 4705 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 4706 OpenMPClauseKind Kind, 4707 bool ParseOnly) { 4708 SourceLocation Loc = Tok.getLocation(); 4709 SourceLocation LOpen = ConsumeToken(); 4710 SmallVector<Expr *, 4> Vars; 4711 Sema::OpenMPVarListDataTy Data; 4712 4713 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 4714 return nullptr; 4715 4716 if (ParseOnly) 4717 return nullptr; 4718 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 4719 return Actions.ActOnOpenMPVarListClause(Kind, Vars, Locs, Data); 4720 } 4721