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 29 using namespace clang; 30 using namespace llvm::omp; 31 32 //===----------------------------------------------------------------------===// 33 // OpenMP declarative directives. 34 //===----------------------------------------------------------------------===// 35 36 namespace { 37 enum OpenMPDirectiveKindEx { 38 OMPD_cancellation = llvm::omp::Directive_enumSize + 1, 39 OMPD_data, 40 OMPD_declare, 41 OMPD_end, 42 OMPD_end_declare, 43 OMPD_enter, 44 OMPD_exit, 45 OMPD_point, 46 OMPD_reduction, 47 OMPD_target_enter, 48 OMPD_target_exit, 49 OMPD_update, 50 OMPD_distribute_parallel, 51 OMPD_teams_distribute_parallel, 52 OMPD_target_teams_distribute_parallel, 53 OMPD_mapper, 54 OMPD_variant, 55 OMPD_begin, 56 OMPD_begin_declare, 57 }; 58 59 // Helper to unify the enum class OpenMPDirectiveKind with its extension 60 // the OpenMPDirectiveKindEx enum which allows to use them together as if they 61 // are unsigned values. 62 struct OpenMPDirectiveKindExWrapper { 63 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {} 64 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {} 65 bool operator==(OpenMPDirectiveKindExWrapper V) const { 66 return Value == V.Value; 67 } 68 bool operator!=(OpenMPDirectiveKindExWrapper V) const { 69 return Value != V.Value; 70 } 71 bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); } 72 bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); } 73 bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); } 74 operator unsigned() const { return Value; } 75 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); } 76 unsigned Value; 77 }; 78 79 class DeclDirectiveListParserHelper final { 80 SmallVector<Expr *, 4> Identifiers; 81 Parser *P; 82 OpenMPDirectiveKind Kind; 83 84 public: 85 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) 86 : P(P), Kind(Kind) {} 87 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 88 ExprResult Res = P->getActions().ActOnOpenMPIdExpression( 89 P->getCurScope(), SS, NameInfo, Kind); 90 if (Res.isUsable()) 91 Identifiers.push_back(Res.get()); 92 } 93 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 94 }; 95 } // namespace 96 97 // Map token string to extended OMP token kind that are 98 // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 99 static unsigned getOpenMPDirectiveKindEx(StringRef S) { 100 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S); 101 if (DKind != OMPD_unknown) 102 return DKind; 103 104 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S) 105 .Case("cancellation", OMPD_cancellation) 106 .Case("data", OMPD_data) 107 .Case("declare", OMPD_declare) 108 .Case("end", OMPD_end) 109 .Case("enter", OMPD_enter) 110 .Case("exit", OMPD_exit) 111 .Case("point", OMPD_point) 112 .Case("reduction", OMPD_reduction) 113 .Case("update", OMPD_update) 114 .Case("mapper", OMPD_mapper) 115 .Case("variant", OMPD_variant) 116 .Case("begin", OMPD_begin) 117 .Default(OMPD_unknown); 118 } 119 120 static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { 121 // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 122 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 123 // TODO: add other combined directives in topological order. 124 static const OpenMPDirectiveKindExWrapper F[][3] = { 125 {OMPD_begin, OMPD_declare, OMPD_begin_declare}, 126 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes}, 127 {OMPD_end, OMPD_declare, OMPD_end_declare}, 128 {OMPD_end, OMPD_assumes, OMPD_end_assumes}, 129 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 130 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 131 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, 132 {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 133 {OMPD_declare, OMPD_target, OMPD_declare_target}, 134 {OMPD_declare, OMPD_variant, OMPD_declare_variant}, 135 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target}, 136 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant}, 137 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant}, 138 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 139 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 140 {OMPD_distribute_parallel_for, OMPD_simd, 141 OMPD_distribute_parallel_for_simd}, 142 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 143 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 144 {OMPD_target, OMPD_data, OMPD_target_data}, 145 {OMPD_target, OMPD_enter, OMPD_target_enter}, 146 {OMPD_target, OMPD_exit, OMPD_target_exit}, 147 {OMPD_target, OMPD_update, OMPD_target_update}, 148 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 149 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 150 {OMPD_for, OMPD_simd, OMPD_for_simd}, 151 {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 152 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 153 {OMPD_parallel, OMPD_loop, OMPD_parallel_loop}, 154 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 155 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 156 {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 157 {OMPD_target, OMPD_simd, OMPD_target_simd}, 158 {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop}, 159 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 160 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 161 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 162 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 163 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 164 {OMPD_teams_distribute_parallel, OMPD_for, 165 OMPD_teams_distribute_parallel_for}, 166 {OMPD_teams_distribute_parallel_for, OMPD_simd, 167 OMPD_teams_distribute_parallel_for_simd}, 168 {OMPD_teams, OMPD_loop, OMPD_teams_loop}, 169 {OMPD_target, OMPD_teams, OMPD_target_teams}, 170 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 171 {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop}, 172 {OMPD_target_teams_distribute, OMPD_parallel, 173 OMPD_target_teams_distribute_parallel}, 174 {OMPD_target_teams_distribute, OMPD_simd, 175 OMPD_target_teams_distribute_simd}, 176 {OMPD_target_teams_distribute_parallel, OMPD_for, 177 OMPD_target_teams_distribute_parallel_for}, 178 {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 179 OMPD_target_teams_distribute_parallel_for_simd}, 180 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, 181 {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop}, 182 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, 183 {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd}, 184 {OMPD_parallel, OMPD_master, OMPD_parallel_master}, 185 {OMPD_parallel, OMPD_masked, OMPD_parallel_masked}, 186 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, 187 {OMPD_parallel_master_taskloop, OMPD_simd, 188 OMPD_parallel_master_taskloop_simd}}; 189 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 190 Token Tok = P.getCurToken(); 191 OpenMPDirectiveKindExWrapper DKind = 192 Tok.isAnnotation() 193 ? static_cast<unsigned>(OMPD_unknown) 194 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 195 if (DKind == OMPD_unknown) 196 return OMPD_unknown; 197 198 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { 199 if (DKind != F[I][0]) 200 continue; 201 202 Tok = P.getPreprocessor().LookAhead(0); 203 OpenMPDirectiveKindExWrapper SDKind = 204 Tok.isAnnotation() 205 ? static_cast<unsigned>(OMPD_unknown) 206 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 207 if (SDKind == OMPD_unknown) 208 continue; 209 210 if (SDKind == F[I][1]) { 211 P.ConsumeToken(); 212 DKind = F[I][2]; 213 } 214 } 215 return unsigned(DKind) < llvm::omp::Directive_enumSize 216 ? static_cast<OpenMPDirectiveKind>(DKind) 217 : OMPD_unknown; 218 } 219 220 static DeclarationName parseOpenMPReductionId(Parser &P) { 221 Token Tok = P.getCurToken(); 222 Sema &Actions = P.getActions(); 223 OverloadedOperatorKind OOK = OO_None; 224 // Allow to use 'operator' keyword for C++ operators 225 bool WithOperator = false; 226 if (Tok.is(tok::kw_operator)) { 227 P.ConsumeToken(); 228 Tok = P.getCurToken(); 229 WithOperator = true; 230 } 231 switch (Tok.getKind()) { 232 case tok::plus: // '+' 233 OOK = OO_Plus; 234 break; 235 case tok::minus: // '-' 236 OOK = OO_Minus; 237 break; 238 case tok::star: // '*' 239 OOK = OO_Star; 240 break; 241 case tok::amp: // '&' 242 OOK = OO_Amp; 243 break; 244 case tok::pipe: // '|' 245 OOK = OO_Pipe; 246 break; 247 case tok::caret: // '^' 248 OOK = OO_Caret; 249 break; 250 case tok::ampamp: // '&&' 251 OOK = OO_AmpAmp; 252 break; 253 case tok::pipepipe: // '||' 254 OOK = OO_PipePipe; 255 break; 256 case tok::identifier: // identifier 257 if (!WithOperator) 258 break; 259 LLVM_FALLTHROUGH; 260 default: 261 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 262 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 263 Parser::StopBeforeMatch); 264 return DeclarationName(); 265 } 266 P.ConsumeToken(); 267 auto &DeclNames = Actions.getASTContext().DeclarationNames; 268 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 269 : DeclNames.getCXXOperatorName(OOK); 270 } 271 272 /// Parse 'omp declare reduction' construct. 273 /// 274 /// declare-reduction-directive: 275 /// annot_pragma_openmp 'declare' 'reduction' 276 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 277 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 278 /// annot_pragma_openmp_end 279 /// <reduction_id> is either a base language identifier or one of the following 280 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 281 /// 282 Parser::DeclGroupPtrTy 283 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 284 // Parse '('. 285 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 286 if (T.expectAndConsume( 287 diag::err_expected_lparen_after, 288 getOpenMPDirectiveName(OMPD_declare_reduction).data())) { 289 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 290 return DeclGroupPtrTy(); 291 } 292 293 DeclarationName Name = parseOpenMPReductionId(*this); 294 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 295 return DeclGroupPtrTy(); 296 297 // Consume ':'. 298 bool IsCorrect = !ExpectAndConsume(tok::colon); 299 300 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 301 return DeclGroupPtrTy(); 302 303 IsCorrect = IsCorrect && !Name.isEmpty(); 304 305 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 306 Diag(Tok.getLocation(), diag::err_expected_type); 307 IsCorrect = false; 308 } 309 310 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 311 return DeclGroupPtrTy(); 312 313 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 314 // Parse list of types until ':' token. 315 do { 316 ColonProtectionRAIIObject ColonRAII(*this); 317 SourceRange Range; 318 TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS); 319 if (TR.isUsable()) { 320 QualType ReductionType = 321 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 322 if (!ReductionType.isNull()) { 323 ReductionTypes.push_back( 324 std::make_pair(ReductionType, Range.getBegin())); 325 } 326 } else { 327 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 328 StopBeforeMatch); 329 } 330 331 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 332 break; 333 334 // Consume ','. 335 if (ExpectAndConsume(tok::comma)) { 336 IsCorrect = false; 337 if (Tok.is(tok::annot_pragma_openmp_end)) { 338 Diag(Tok.getLocation(), diag::err_expected_type); 339 return DeclGroupPtrTy(); 340 } 341 } 342 } while (Tok.isNot(tok::annot_pragma_openmp_end)); 343 344 if (ReductionTypes.empty()) { 345 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 346 return DeclGroupPtrTy(); 347 } 348 349 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 350 return DeclGroupPtrTy(); 351 352 // Consume ':'. 353 if (ExpectAndConsume(tok::colon)) 354 IsCorrect = false; 355 356 if (Tok.is(tok::annot_pragma_openmp_end)) { 357 Diag(Tok.getLocation(), diag::err_expected_expression); 358 return DeclGroupPtrTy(); 359 } 360 361 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 362 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 363 364 // Parse <combiner> expression and then parse initializer if any for each 365 // correct type. 366 unsigned I = 0, E = ReductionTypes.size(); 367 for (Decl *D : DRD.get()) { 368 TentativeParsingAction TPA(*this); 369 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 370 Scope::CompoundStmtScope | 371 Scope::OpenMPDirectiveScope); 372 // Parse <combiner> expression. 373 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 374 ExprResult CombinerResult = Actions.ActOnFinishFullExpr( 375 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false); 376 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 377 378 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 379 Tok.isNot(tok::annot_pragma_openmp_end)) { 380 TPA.Commit(); 381 IsCorrect = false; 382 break; 383 } 384 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 385 ExprResult InitializerResult; 386 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 387 // Parse <initializer> expression. 388 if (Tok.is(tok::identifier) && 389 Tok.getIdentifierInfo()->isStr("initializer")) { 390 ConsumeToken(); 391 } else { 392 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 393 TPA.Commit(); 394 IsCorrect = false; 395 break; 396 } 397 // Parse '('. 398 BalancedDelimiterTracker T(*this, tok::l_paren, 399 tok::annot_pragma_openmp_end); 400 IsCorrect = 401 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 402 IsCorrect; 403 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 404 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 405 Scope::CompoundStmtScope | 406 Scope::OpenMPDirectiveScope); 407 // Parse expression. 408 VarDecl *OmpPrivParm = 409 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 410 D); 411 // Check if initializer is omp_priv <init_expr> or something else. 412 if (Tok.is(tok::identifier) && 413 Tok.getIdentifierInfo()->isStr("omp_priv")) { 414 ConsumeToken(); 415 ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 416 } else { 417 InitializerResult = Actions.ActOnFinishFullExpr( 418 ParseAssignmentExpression().get(), D->getLocation(), 419 /*DiscardedValue*/ false); 420 } 421 Actions.ActOnOpenMPDeclareReductionInitializerEnd( 422 D, InitializerResult.get(), OmpPrivParm); 423 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 424 Tok.isNot(tok::annot_pragma_openmp_end)) { 425 TPA.Commit(); 426 IsCorrect = false; 427 break; 428 } 429 IsCorrect = 430 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 431 } 432 } 433 434 ++I; 435 // Revert parsing if not the last type, otherwise accept it, we're done with 436 // parsing. 437 if (I != E) 438 TPA.Revert(); 439 else 440 TPA.Commit(); 441 } 442 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 443 IsCorrect); 444 } 445 446 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 447 // Parse declarator '=' initializer. 448 // If a '==' or '+=' is found, suggest a fixit to '='. 449 if (isTokenEqualOrEqualTypo()) { 450 ConsumeToken(); 451 452 if (Tok.is(tok::code_completion)) { 453 cutOffParsing(); 454 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 455 Actions.FinalizeDeclaration(OmpPrivParm); 456 return; 457 } 458 459 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm); 460 ExprResult Init = ParseInitializer(); 461 462 if (Init.isInvalid()) { 463 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 464 Actions.ActOnInitializerError(OmpPrivParm); 465 } else { 466 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 467 /*DirectInit=*/false); 468 } 469 } else if (Tok.is(tok::l_paren)) { 470 // Parse C++ direct initializer: '(' expression-list ')' 471 BalancedDelimiterTracker T(*this, tok::l_paren); 472 T.consumeOpen(); 473 474 ExprVector Exprs; 475 CommaLocsTy CommaLocs; 476 477 SourceLocation LParLoc = T.getOpenLocation(); 478 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { 479 QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 480 OmpPrivParm->getType()->getCanonicalTypeInternal(), 481 OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false); 482 CalledSignatureHelp = true; 483 return PreferredType; 484 }; 485 if (ParseExpressionList(Exprs, CommaLocs, [&] { 486 PreferredType.enterFunctionArgument(Tok.getLocation(), 487 RunSignatureHelp); 488 })) { 489 if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 490 RunSignatureHelp(); 491 Actions.ActOnInitializerError(OmpPrivParm); 492 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 493 } else { 494 // Match the ')'. 495 SourceLocation RLoc = Tok.getLocation(); 496 if (!T.consumeClose()) 497 RLoc = T.getCloseLocation(); 498 499 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && 500 "Unexpected number of commas!"); 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<OMPDeclareVariantAttr::InteropType, 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 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 /// Parse a list of interop-types. These are 'target' and 'targetsync'. Both 1503 /// are allowed but duplication of either is not meaningful. 1504 static Optional<OMPDeclareVariantAttr::InteropType> 1505 parseInteropTypeList(Parser &P) { 1506 const Token &Tok = P.getCurToken(); 1507 bool HasError = false; 1508 bool IsTarget = false; 1509 bool IsTargetSync = false; 1510 1511 while (Tok.is(tok::identifier)) { 1512 if (Tok.getIdentifierInfo()->isStr("target")) { 1513 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 1514 // Each interop-type may be specified on an action-clause at most 1515 // once. 1516 if (IsTarget) 1517 P.Diag(Tok, diag::warn_omp_more_one_interop_type) << "target"; 1518 IsTarget = true; 1519 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) { 1520 if (IsTargetSync) 1521 P.Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync"; 1522 IsTargetSync = true; 1523 } else { 1524 HasError = true; 1525 P.Diag(Tok, diag::err_omp_expected_interop_type); 1526 } 1527 P.ConsumeToken(); 1528 1529 if (!Tok.is(tok::comma)) 1530 break; 1531 P.ConsumeToken(); 1532 } 1533 if (HasError) 1534 return None; 1535 1536 if (!IsTarget && !IsTargetSync) { 1537 P.Diag(Tok, diag::err_omp_expected_interop_type); 1538 return None; 1539 } 1540 1541 // As of OpenMP 5.1,there are two interop-types, "target" and 1542 // "targetsync". Either or both are allowed for a single interop. 1543 if (IsTarget && IsTargetSync) 1544 return OMPDeclareVariantAttr::Target_TargetSync; 1545 if (IsTarget) 1546 return OMPDeclareVariantAttr::Target; 1547 return OMPDeclareVariantAttr::TargetSync; 1548 } 1549 1550 bool Parser::parseOpenMPAppendArgs( 1551 SmallVectorImpl<OMPDeclareVariantAttr::InteropType> &InterOpTypes) { 1552 bool HasError = false; 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_append_args).data())) 1557 return true; 1558 1559 // Parse the list of append-ops, each is; 1560 // interop(interop-type[,interop-type]...) 1561 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) { 1562 ConsumeToken(); 1563 BalancedDelimiterTracker IT(*this, tok::l_paren, 1564 tok::annot_pragma_openmp_end); 1565 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop")) 1566 return true; 1567 1568 // Parse the interop-types. 1569 if (Optional<OMPDeclareVariantAttr::InteropType> IType = 1570 parseInteropTypeList(*this)) 1571 InterOpTypes.push_back(*IType); 1572 else 1573 HasError = true; 1574 1575 IT.consumeClose(); 1576 if (Tok.is(tok::comma)) 1577 ConsumeToken(); 1578 } 1579 if (!HasError && InterOpTypes.empty()) { 1580 HasError = true; 1581 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op); 1582 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1583 StopBeforeMatch); 1584 } 1585 HasError = T.consumeClose() || HasError; 1586 return HasError; 1587 } 1588 1589 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, 1590 OMPTraitInfo &TI, 1591 OMPTraitInfo *ParentTI) { 1592 // Parse 'match'. 1593 OpenMPClauseKind CKind = Tok.isAnnotation() 1594 ? OMPC_unknown 1595 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1596 if (CKind != OMPC_match) { 1597 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1598 << (getLangOpts().OpenMP < 51 ? 0 : 1); 1599 return true; 1600 } 1601 (void)ConsumeToken(); 1602 // Parse '('. 1603 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1604 if (T.expectAndConsume(diag::err_expected_lparen_after, 1605 getOpenMPClauseName(OMPC_match).data())) 1606 return true; 1607 1608 // Parse inner context selectors. 1609 parseOMPContextSelectors(Loc, TI); 1610 1611 // Parse ')' 1612 (void)T.consumeClose(); 1613 1614 if (!ParentTI) 1615 return false; 1616 1617 // Merge the parent/outer trait info into the one we just parsed and diagnose 1618 // problems. 1619 // TODO: Keep some source location in the TI to provide better diagnostics. 1620 // TODO: Perform some kind of equivalence check on the condition and score 1621 // expressions. 1622 for (const OMPTraitSet &ParentSet : ParentTI->Sets) { 1623 bool MergedSet = false; 1624 for (OMPTraitSet &Set : TI.Sets) { 1625 if (Set.Kind != ParentSet.Kind) 1626 continue; 1627 MergedSet = true; 1628 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) { 1629 bool MergedSelector = false; 1630 for (OMPTraitSelector &Selector : Set.Selectors) { 1631 if (Selector.Kind != ParentSelector.Kind) 1632 continue; 1633 MergedSelector = true; 1634 for (const OMPTraitProperty &ParentProperty : 1635 ParentSelector.Properties) { 1636 bool MergedProperty = false; 1637 for (OMPTraitProperty &Property : Selector.Properties) { 1638 // Ignore "equivalent" properties. 1639 if (Property.Kind != ParentProperty.Kind) 1640 continue; 1641 1642 // If the kind is the same but the raw string not, we don't want 1643 // to skip out on the property. 1644 MergedProperty |= Property.RawString == ParentProperty.RawString; 1645 1646 if (Property.RawString == ParentProperty.RawString && 1647 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition) 1648 continue; 1649 1650 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) { 1651 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition); 1652 } else if (Selector.ScoreOrCondition != 1653 ParentSelector.ScoreOrCondition) { 1654 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait) 1655 << getOpenMPContextTraitPropertyName( 1656 ParentProperty.Kind, ParentProperty.RawString) 1657 << getOpenMPContextTraitSelectorName(ParentSelector.Kind) 1658 << getOpenMPContextTraitSetName(ParentSet.Kind); 1659 } 1660 } 1661 if (!MergedProperty) 1662 Selector.Properties.push_back(ParentProperty); 1663 } 1664 } 1665 if (!MergedSelector) 1666 Set.Selectors.push_back(ParentSelector); 1667 } 1668 } 1669 if (!MergedSet) 1670 TI.Sets.push_back(ParentSet); 1671 } 1672 1673 return false; 1674 } 1675 1676 /// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]... 1677 /// where 1678 /// 1679 /// clause: 1680 /// 'ext_IMPL_DEFINED' 1681 /// 'absent' '(' directive-name [, directive-name]* ')' 1682 /// 'contains' '(' directive-name [, directive-name]* ')' 1683 /// 'holds' '(' scalar-expression ')' 1684 /// 'no_openmp' 1685 /// 'no_openmp_routines' 1686 /// 'no_parallelism' 1687 /// 1688 void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind, 1689 SourceLocation Loc) { 1690 SmallVector<std::string, 4> Assumptions; 1691 bool SkippedClauses = false; 1692 1693 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) { 1694 BalancedDelimiterTracker T(*this, tok::l_paren, 1695 tok::annot_pragma_openmp_end); 1696 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data())) 1697 return; 1698 T.skipToEnd(); 1699 if (IssueNote && T.getCloseLocation().isValid()) 1700 Diag(T.getCloseLocation(), 1701 diag::note_omp_assumption_clause_continue_here); 1702 }; 1703 1704 /// Helper to determine which AssumptionClauseMapping (ACM) in the 1705 /// AssumptionClauseMappings table matches \p RawString. The return value is 1706 /// the index of the matching ACM into the table or -1 if there was no match. 1707 auto MatchACMClause = [&](StringRef RawString) { 1708 llvm::StringSwitch<int> SS(RawString); 1709 unsigned ACMIdx = 0; 1710 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) { 1711 if (ACMI.StartsWith) 1712 SS.StartsWith(ACMI.Identifier, ACMIdx++); 1713 else 1714 SS.Case(ACMI.Identifier, ACMIdx++); 1715 } 1716 return SS.Default(-1); 1717 }; 1718 1719 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1720 IdentifierInfo *II = nullptr; 1721 SourceLocation StartLoc = Tok.getLocation(); 1722 int Idx = -1; 1723 if (Tok.isAnyIdentifier()) { 1724 II = Tok.getIdentifierInfo(); 1725 Idx = MatchACMClause(II->getName()); 1726 } 1727 ConsumeAnyToken(); 1728 1729 bool NextIsLPar = Tok.is(tok::l_paren); 1730 // Handle unknown clauses by skipping them. 1731 if (Idx == -1) { 1732 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id) 1733 << llvm::omp::getOpenMPDirectiveName(DKind) 1734 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar; 1735 if (NextIsLPar) 1736 SkipBraces(II ? II->getName() : "", /* IssueNote */ true); 1737 SkippedClauses = true; 1738 continue; 1739 } 1740 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx]; 1741 if (ACMI.HasDirectiveList || ACMI.HasExpression) { 1742 // TODO: We ignore absent, contains, and holds assumptions for now. We 1743 // also do not verify the content in the parenthesis at all. 1744 SkippedClauses = true; 1745 SkipBraces(II->getName(), /* IssueNote */ false); 1746 continue; 1747 } 1748 1749 if (NextIsLPar) { 1750 Diag(Tok.getLocation(), 1751 diag::warn_omp_unknown_assumption_clause_without_args) 1752 << II; 1753 SkipBraces(II->getName(), /* IssueNote */ true); 1754 } 1755 1756 assert(II && "Expected an identifier clause!"); 1757 std::string Assumption = II->getName().str(); 1758 if (ACMI.StartsWith) 1759 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size()); 1760 else 1761 Assumption = "omp_" + Assumption; 1762 Assumptions.push_back(Assumption); 1763 } 1764 1765 Actions.ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions, SkippedClauses); 1766 } 1767 1768 void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) { 1769 if (Actions.isInOpenMPAssumeScope()) 1770 Actions.ActOnOpenMPEndAssumesDirective(); 1771 else 1772 Diag(Loc, diag::err_expected_begin_assumes); 1773 } 1774 1775 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1776 /// 1777 /// default-clause: 1778 /// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ') 1779 /// 1780 /// proc_bind-clause: 1781 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1782 /// 1783 /// device_type-clause: 1784 /// 'device_type' '(' 'host' | 'nohost' | 'any' )' 1785 namespace { 1786 struct SimpleClauseData { 1787 unsigned Type; 1788 SourceLocation Loc; 1789 SourceLocation LOpen; 1790 SourceLocation TypeLoc; 1791 SourceLocation RLoc; 1792 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, 1793 SourceLocation TypeLoc, SourceLocation RLoc) 1794 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} 1795 }; 1796 } // anonymous namespace 1797 1798 static Optional<SimpleClauseData> 1799 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { 1800 const Token &Tok = P.getCurToken(); 1801 SourceLocation Loc = Tok.getLocation(); 1802 SourceLocation LOpen = P.ConsumeToken(); 1803 // Parse '('. 1804 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 1805 if (T.expectAndConsume(diag::err_expected_lparen_after, 1806 getOpenMPClauseName(Kind).data())) 1807 return llvm::None; 1808 1809 unsigned Type = getOpenMPSimpleClauseType( 1810 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok), 1811 P.getLangOpts()); 1812 SourceLocation TypeLoc = Tok.getLocation(); 1813 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1814 Tok.isNot(tok::annot_pragma_openmp_end)) 1815 P.ConsumeAnyToken(); 1816 1817 // Parse ')'. 1818 SourceLocation RLoc = Tok.getLocation(); 1819 if (!T.consumeClose()) 1820 RLoc = T.getCloseLocation(); 1821 1822 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); 1823 } 1824 1825 void Parser::ParseOMPDeclareTargetClauses( 1826 Sema::DeclareTargetContextInfo &DTCI) { 1827 SourceLocation DeviceTypeLoc; 1828 bool RequiresToOrLinkOrIndirectClause = false; 1829 bool HasToOrLinkOrIndirectClause = false; 1830 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1831 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 1832 bool HasIdentifier = Tok.is(tok::identifier); 1833 if (HasIdentifier) { 1834 // If we see any clause we need a to or link clause. 1835 RequiresToOrLinkOrIndirectClause = true; 1836 IdentifierInfo *II = Tok.getIdentifierInfo(); 1837 StringRef ClauseName = II->getName(); 1838 bool IsDeviceTypeClause = 1839 getLangOpts().OpenMP >= 50 && 1840 getOpenMPClauseKind(ClauseName) == OMPC_device_type; 1841 1842 bool IsIndirectClause = getLangOpts().OpenMP >= 51 && 1843 getOpenMPClauseKind(ClauseName) == OMPC_indirect; 1844 if (DTCI.Indirect && IsIndirectClause) { 1845 Diag(Tok, diag::err_omp_more_one_clause) 1846 << getOpenMPDirectiveName(OMPD_declare_target) 1847 << getOpenMPClauseName(OMPC_indirect) << 0; 1848 break; 1849 } 1850 bool IsToOrLinkClause = 1851 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT); 1852 assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!"); 1853 1854 if (!IsDeviceTypeClause && !IsIndirectClause && 1855 DTCI.Kind == OMPD_begin_declare_target) { 1856 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1857 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0); 1858 break; 1859 } 1860 if (!IsDeviceTypeClause && !IsToOrLinkClause && !IsIndirectClause) { 1861 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1862 << ClauseName 1863 << (getLangOpts().OpenMP >= 51 ? 4 1864 : getLangOpts().OpenMP >= 50 ? 2 1865 : 1); 1866 break; 1867 } 1868 1869 if (IsToOrLinkClause || IsIndirectClause) 1870 HasToOrLinkOrIndirectClause = true; 1871 1872 if (IsIndirectClause) { 1873 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false)) 1874 break; 1875 continue; 1876 } 1877 // Parse 'device_type' clause and go to next clause if any. 1878 if (IsDeviceTypeClause) { 1879 Optional<SimpleClauseData> DevTypeData = 1880 parseOpenMPSimpleClause(*this, OMPC_device_type); 1881 if (DevTypeData) { 1882 if (DeviceTypeLoc.isValid()) { 1883 // We already saw another device_type clause, diagnose it. 1884 Diag(DevTypeData.getValue().Loc, 1885 diag::warn_omp_more_one_device_type_clause); 1886 break; 1887 } 1888 switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { 1889 case OMPC_DEVICE_TYPE_any: 1890 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any; 1891 break; 1892 case OMPC_DEVICE_TYPE_host: 1893 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host; 1894 break; 1895 case OMPC_DEVICE_TYPE_nohost: 1896 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost; 1897 break; 1898 case OMPC_DEVICE_TYPE_unknown: 1899 llvm_unreachable("Unexpected device_type"); 1900 } 1901 DeviceTypeLoc = DevTypeData->Loc; 1902 } 1903 continue; 1904 } 1905 ConsumeToken(); 1906 } 1907 1908 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) { 1909 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS, 1910 DeclarationNameInfo NameInfo) { 1911 NamedDecl *ND = 1912 Actions.lookupOpenMPDeclareTargetName(getCurScope(), SS, NameInfo); 1913 if (!ND) 1914 return; 1915 Sema::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()}; 1916 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second; 1917 if (!FirstMapping) 1918 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple) 1919 << NameInfo.getName(); 1920 }; 1921 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 1922 /*AllowScopeSpecifier=*/true)) 1923 break; 1924 } 1925 1926 if (Tok.is(tok::l_paren)) { 1927 Diag(Tok, 1928 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause); 1929 break; 1930 } 1931 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) { 1932 Diag(Tok, 1933 diag::err_omp_declare_target_unexpected_clause_after_implicit_to); 1934 break; 1935 } 1936 1937 // Consume optional ','. 1938 if (Tok.is(tok::comma)) 1939 ConsumeToken(); 1940 } 1941 1942 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any) 1943 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type); 1944 1945 // For declare target require at least 'to' or 'link' to be present. 1946 if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause && 1947 !HasToOrLinkOrIndirectClause) 1948 Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause) 1949 << (getLangOpts().OpenMP >= 51 ? 1 : 0); 1950 1951 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1952 } 1953 1954 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) { 1955 // The last seen token is annot_pragma_openmp_end - need to check for 1956 // extra tokens. 1957 if (Tok.is(tok::annot_pragma_openmp_end)) 1958 return; 1959 1960 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1961 << getOpenMPDirectiveName(DKind); 1962 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1963 ConsumeAnyToken(); 1964 } 1965 1966 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind, 1967 OpenMPDirectiveKind ExpectedKind, 1968 OpenMPDirectiveKind FoundKind, 1969 SourceLocation BeginLoc, 1970 SourceLocation FoundLoc, 1971 bool SkipUntilOpenMPEnd) { 1972 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1; 1973 1974 if (FoundKind == ExpectedKind) { 1975 ConsumeAnyToken(); 1976 skipUntilPragmaOpenMPEnd(ExpectedKind); 1977 return; 1978 } 1979 1980 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant) 1981 << DiagSelection; 1982 Diag(BeginLoc, diag::note_matching) 1983 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str(); 1984 if (SkipUntilOpenMPEnd) 1985 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1986 } 1987 1988 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind, 1989 OpenMPDirectiveKind EndDKind, 1990 SourceLocation DKLoc) { 1991 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc, 1992 Tok.getLocation(), 1993 /* SkipUntilOpenMPEnd */ false); 1994 // Skip the last annot_pragma_openmp_end. 1995 if (Tok.is(tok::annot_pragma_openmp_end)) 1996 ConsumeAnnotationToken(); 1997 } 1998 1999 /// Parsing of declarative OpenMP directives. 2000 /// 2001 /// threadprivate-directive: 2002 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2003 /// annot_pragma_openmp_end 2004 /// 2005 /// allocate-directive: 2006 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 2007 /// annot_pragma_openmp_end 2008 /// 2009 /// declare-reduction-directive: 2010 /// annot_pragma_openmp 'declare' 'reduction' [...] 2011 /// annot_pragma_openmp_end 2012 /// 2013 /// declare-mapper-directive: 2014 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2015 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2016 /// annot_pragma_openmp_end 2017 /// 2018 /// declare-simd-directive: 2019 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 2020 /// annot_pragma_openmp_end 2021 /// <function declaration/definition> 2022 /// 2023 /// requires directive: 2024 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 2025 /// annot_pragma_openmp_end 2026 /// 2027 /// assumes directive: 2028 /// annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ] 2029 /// annot_pragma_openmp_end 2030 /// or 2031 /// annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ] 2032 /// annot_pragma_openmp 'end assumes' 2033 /// annot_pragma_openmp_end 2034 /// 2035 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 2036 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed, 2037 DeclSpec::TST TagType, Decl *Tag) { 2038 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && 2039 "Not an OpenMP directive!"); 2040 ParsingOpenMPDirectiveRAII DirScope(*this); 2041 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2042 2043 SourceLocation Loc; 2044 OpenMPDirectiveKind DKind; 2045 if (Delayed) { 2046 TentativeParsingAction TPA(*this); 2047 Loc = ConsumeAnnotationToken(); 2048 DKind = parseOpenMPDirectiveKind(*this); 2049 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { 2050 // Need to delay parsing until completion of the parent class. 2051 TPA.Revert(); 2052 CachedTokens Toks; 2053 unsigned Cnt = 1; 2054 Toks.push_back(Tok); 2055 while (Cnt && Tok.isNot(tok::eof)) { 2056 (void)ConsumeAnyToken(); 2057 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) 2058 ++Cnt; 2059 else if (Tok.is(tok::annot_pragma_openmp_end)) 2060 --Cnt; 2061 Toks.push_back(Tok); 2062 } 2063 // Skip last annot_pragma_openmp_end. 2064 if (Cnt == 0) 2065 (void)ConsumeAnyToken(); 2066 auto *LP = new LateParsedPragma(this, AS); 2067 LP->takeToks(Toks); 2068 getCurrentClass().LateParsedDeclarations.push_back(LP); 2069 return nullptr; 2070 } 2071 TPA.Commit(); 2072 } else { 2073 Loc = ConsumeAnnotationToken(); 2074 DKind = parseOpenMPDirectiveKind(*this); 2075 } 2076 2077 switch (DKind) { 2078 case OMPD_threadprivate: { 2079 ConsumeToken(); 2080 DeclDirectiveListParserHelper Helper(this, DKind); 2081 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2082 /*AllowScopeSpecifier=*/true)) { 2083 skipUntilPragmaOpenMPEnd(DKind); 2084 // Skip the last annot_pragma_openmp_end. 2085 ConsumeAnnotationToken(); 2086 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 2087 Helper.getIdentifiers()); 2088 } 2089 break; 2090 } 2091 case OMPD_allocate: { 2092 ConsumeToken(); 2093 DeclDirectiveListParserHelper Helper(this, DKind); 2094 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2095 /*AllowScopeSpecifier=*/true)) { 2096 SmallVector<OMPClause *, 1> Clauses; 2097 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2098 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2099 llvm::omp::Clause_enumSize + 1> 2100 FirstClauses(llvm::omp::Clause_enumSize + 1); 2101 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2102 OpenMPClauseKind CKind = 2103 Tok.isAnnotation() ? OMPC_unknown 2104 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2105 Actions.StartOpenMPClause(CKind); 2106 OMPClause *Clause = ParseOpenMPClause( 2107 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2108 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2109 StopBeforeMatch); 2110 FirstClauses[unsigned(CKind)].setInt(true); 2111 if (Clause != nullptr) 2112 Clauses.push_back(Clause); 2113 if (Tok.is(tok::annot_pragma_openmp_end)) { 2114 Actions.EndOpenMPClause(); 2115 break; 2116 } 2117 // Skip ',' if any. 2118 if (Tok.is(tok::comma)) 2119 ConsumeToken(); 2120 Actions.EndOpenMPClause(); 2121 } 2122 skipUntilPragmaOpenMPEnd(DKind); 2123 } 2124 // Skip the last annot_pragma_openmp_end. 2125 ConsumeAnnotationToken(); 2126 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 2127 Clauses); 2128 } 2129 break; 2130 } 2131 case OMPD_requires: { 2132 SourceLocation StartLoc = ConsumeToken(); 2133 SmallVector<OMPClause *, 5> Clauses; 2134 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2135 llvm::omp::Clause_enumSize + 1> 2136 FirstClauses(llvm::omp::Clause_enumSize + 1); 2137 if (Tok.is(tok::annot_pragma_openmp_end)) { 2138 Diag(Tok, diag::err_omp_expected_clause) 2139 << getOpenMPDirectiveName(OMPD_requires); 2140 break; 2141 } 2142 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2143 OpenMPClauseKind CKind = Tok.isAnnotation() 2144 ? OMPC_unknown 2145 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2146 Actions.StartOpenMPClause(CKind); 2147 OMPClause *Clause = ParseOpenMPClause( 2148 OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2149 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2150 StopBeforeMatch); 2151 FirstClauses[unsigned(CKind)].setInt(true); 2152 if (Clause != nullptr) 2153 Clauses.push_back(Clause); 2154 if (Tok.is(tok::annot_pragma_openmp_end)) { 2155 Actions.EndOpenMPClause(); 2156 break; 2157 } 2158 // Skip ',' if any. 2159 if (Tok.is(tok::comma)) 2160 ConsumeToken(); 2161 Actions.EndOpenMPClause(); 2162 } 2163 // Consume final annot_pragma_openmp_end 2164 if (Clauses.empty()) { 2165 Diag(Tok, diag::err_omp_expected_clause) 2166 << getOpenMPDirectiveName(OMPD_requires); 2167 ConsumeAnnotationToken(); 2168 return nullptr; 2169 } 2170 ConsumeAnnotationToken(); 2171 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 2172 } 2173 case OMPD_assumes: 2174 case OMPD_begin_assumes: 2175 ParseOpenMPAssumesDirective(DKind, ConsumeToken()); 2176 break; 2177 case OMPD_end_assumes: 2178 ParseOpenMPEndAssumesDirective(ConsumeToken()); 2179 break; 2180 case OMPD_declare_reduction: 2181 ConsumeToken(); 2182 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 2183 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2184 // Skip the last annot_pragma_openmp_end. 2185 ConsumeAnnotationToken(); 2186 return Res; 2187 } 2188 break; 2189 case OMPD_declare_mapper: { 2190 ConsumeToken(); 2191 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 2192 // Skip the last annot_pragma_openmp_end. 2193 ConsumeAnnotationToken(); 2194 return Res; 2195 } 2196 break; 2197 } 2198 case OMPD_begin_declare_variant: { 2199 // The syntax is: 2200 // { #pragma omp begin declare variant clause } 2201 // <function-declaration-or-definition-sequence> 2202 // { #pragma omp end declare variant } 2203 // 2204 ConsumeToken(); 2205 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope(); 2206 ASTContext &ASTCtx = Actions.getASTContext(); 2207 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); 2208 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) { 2209 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 2210 ; 2211 // Skip the last annot_pragma_openmp_end. 2212 (void)ConsumeAnnotationToken(); 2213 break; 2214 } 2215 2216 // Skip last tokens. 2217 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant); 2218 2219 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2220 2221 VariantMatchInfo VMI; 2222 TI.getAsVariantMatchInfo(ASTCtx, VMI); 2223 2224 std::function<void(StringRef)> DiagUnknownTrait = 2225 [this, Loc](StringRef ISATrait) { 2226 // TODO Track the selector locations in a way that is accessible here 2227 // to improve the diagnostic location. 2228 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; 2229 }; 2230 TargetOMPContext OMPCtx( 2231 ASTCtx, std::move(DiagUnknownTrait), 2232 /* CurrentFunctionDecl */ nullptr, 2233 /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>()); 2234 2235 if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) { 2236 Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI); 2237 break; 2238 } 2239 2240 // Elide all the code till the matching end declare variant was found. 2241 unsigned Nesting = 1; 2242 SourceLocation DKLoc; 2243 OpenMPDirectiveKind DK = OMPD_unknown; 2244 do { 2245 DKLoc = Tok.getLocation(); 2246 DK = parseOpenMPDirectiveKind(*this); 2247 if (DK == OMPD_end_declare_variant) 2248 --Nesting; 2249 else if (DK == OMPD_begin_declare_variant) 2250 ++Nesting; 2251 if (!Nesting || isEofOrEom()) 2252 break; 2253 ConsumeAnyToken(); 2254 } while (true); 2255 2256 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, 2257 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true); 2258 if (isEofOrEom()) 2259 return nullptr; 2260 break; 2261 } 2262 case OMPD_end_declare_variant: { 2263 if (Actions.isInOpenMPDeclareVariantScope()) 2264 Actions.ActOnOpenMPEndDeclareVariant(); 2265 else 2266 Diag(Loc, diag::err_expected_begin_declare_variant); 2267 ConsumeToken(); 2268 break; 2269 } 2270 case OMPD_declare_variant: 2271 case OMPD_declare_simd: { 2272 // The syntax is: 2273 // { #pragma omp declare {simd|variant} } 2274 // <function-declaration-or-definition> 2275 // 2276 CachedTokens Toks; 2277 Toks.push_back(Tok); 2278 ConsumeToken(); 2279 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2280 Toks.push_back(Tok); 2281 ConsumeAnyToken(); 2282 } 2283 Toks.push_back(Tok); 2284 ConsumeAnyToken(); 2285 2286 DeclGroupPtrTy Ptr; 2287 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) { 2288 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, 2289 TagType, Tag); 2290 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 2291 // Here we expect to see some function declaration. 2292 if (AS == AS_none) { 2293 assert(TagType == DeclSpec::TST_unspecified); 2294 MaybeParseCXX11Attributes(Attrs); 2295 ParsingDeclSpec PDS(*this); 2296 Ptr = ParseExternalDeclaration(Attrs, &PDS); 2297 } else { 2298 Ptr = 2299 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 2300 } 2301 } 2302 if (!Ptr) { 2303 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) 2304 << (DKind == OMPD_declare_simd ? 0 : 1); 2305 return DeclGroupPtrTy(); 2306 } 2307 if (DKind == OMPD_declare_simd) 2308 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 2309 assert(DKind == OMPD_declare_variant && 2310 "Expected declare variant directive only"); 2311 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); 2312 return Ptr; 2313 } 2314 case OMPD_begin_declare_target: 2315 case OMPD_declare_target: { 2316 SourceLocation DTLoc = ConsumeAnyToken(); 2317 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end); 2318 Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc); 2319 if (HasClauses) 2320 ParseOMPDeclareTargetClauses(DTCI); 2321 bool HasImplicitMappings = DKind == OMPD_begin_declare_target || 2322 !HasClauses || 2323 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect); 2324 2325 // Skip the last annot_pragma_openmp_end. 2326 ConsumeAnyToken(); 2327 2328 if (HasImplicitMappings) { 2329 Actions.ActOnStartOpenMPDeclareTargetContext(DTCI); 2330 return nullptr; 2331 } 2332 2333 Actions.ActOnFinishedOpenMPDeclareTargetContext(DTCI); 2334 llvm::SmallVector<Decl *, 4> Decls; 2335 for (auto &It : DTCI.ExplicitlyMapped) 2336 Decls.push_back(It.first); 2337 return Actions.BuildDeclaratorGroup(Decls); 2338 } 2339 case OMPD_end_declare_target: { 2340 if (!Actions.isInOpenMPDeclareTargetContext()) { 2341 Diag(Tok, diag::err_omp_unexpected_directive) 2342 << 1 << getOpenMPDirectiveName(DKind); 2343 break; 2344 } 2345 const Sema::DeclareTargetContextInfo &DTCI = 2346 Actions.ActOnOpenMPEndDeclareTargetDirective(); 2347 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc); 2348 return nullptr; 2349 } 2350 case OMPD_unknown: 2351 Diag(Tok, diag::err_omp_unknown_directive); 2352 break; 2353 case OMPD_parallel: 2354 case OMPD_simd: 2355 case OMPD_tile: 2356 case OMPD_unroll: 2357 case OMPD_task: 2358 case OMPD_taskyield: 2359 case OMPD_barrier: 2360 case OMPD_taskwait: 2361 case OMPD_taskgroup: 2362 case OMPD_flush: 2363 case OMPD_depobj: 2364 case OMPD_scan: 2365 case OMPD_for: 2366 case OMPD_for_simd: 2367 case OMPD_sections: 2368 case OMPD_section: 2369 case OMPD_single: 2370 case OMPD_master: 2371 case OMPD_ordered: 2372 case OMPD_critical: 2373 case OMPD_parallel_for: 2374 case OMPD_parallel_for_simd: 2375 case OMPD_parallel_sections: 2376 case OMPD_parallel_master: 2377 case OMPD_parallel_masked: 2378 case OMPD_atomic: 2379 case OMPD_target: 2380 case OMPD_teams: 2381 case OMPD_cancellation_point: 2382 case OMPD_cancel: 2383 case OMPD_target_data: 2384 case OMPD_target_enter_data: 2385 case OMPD_target_exit_data: 2386 case OMPD_target_parallel: 2387 case OMPD_target_parallel_for: 2388 case OMPD_taskloop: 2389 case OMPD_taskloop_simd: 2390 case OMPD_master_taskloop: 2391 case OMPD_master_taskloop_simd: 2392 case OMPD_parallel_master_taskloop: 2393 case OMPD_parallel_master_taskloop_simd: 2394 case OMPD_masked_taskloop: 2395 case OMPD_masked_taskloop_simd: 2396 case OMPD_distribute: 2397 case OMPD_target_update: 2398 case OMPD_distribute_parallel_for: 2399 case OMPD_distribute_parallel_for_simd: 2400 case OMPD_distribute_simd: 2401 case OMPD_target_parallel_for_simd: 2402 case OMPD_target_simd: 2403 case OMPD_teams_distribute: 2404 case OMPD_teams_distribute_simd: 2405 case OMPD_teams_distribute_parallel_for_simd: 2406 case OMPD_teams_distribute_parallel_for: 2407 case OMPD_target_teams: 2408 case OMPD_target_teams_distribute: 2409 case OMPD_target_teams_distribute_parallel_for: 2410 case OMPD_target_teams_distribute_parallel_for_simd: 2411 case OMPD_target_teams_distribute_simd: 2412 case OMPD_dispatch: 2413 case OMPD_masked: 2414 case OMPD_metadirective: 2415 case OMPD_loop: 2416 case OMPD_teams_loop: 2417 case OMPD_target_teams_loop: 2418 case OMPD_parallel_loop: 2419 case OMPD_target_parallel_loop: 2420 Diag(Tok, diag::err_omp_unexpected_directive) 2421 << 1 << getOpenMPDirectiveName(DKind); 2422 break; 2423 default: 2424 break; 2425 } 2426 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2427 ConsumeAnyToken(); 2428 ConsumeAnyToken(); 2429 return nullptr; 2430 } 2431 2432 /// Parsing of declarative or executable OpenMP directives. 2433 /// 2434 /// threadprivate-directive: 2435 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2436 /// annot_pragma_openmp_end 2437 /// 2438 /// allocate-directive: 2439 /// annot_pragma_openmp 'allocate' simple-variable-list 2440 /// annot_pragma_openmp_end 2441 /// 2442 /// declare-reduction-directive: 2443 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 2444 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 2445 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 2446 /// annot_pragma_openmp_end 2447 /// 2448 /// declare-mapper-directive: 2449 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2450 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2451 /// annot_pragma_openmp_end 2452 /// 2453 /// executable-directive: 2454 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 2455 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 2456 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | 2457 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 2458 /// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target 2459 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 2460 /// 'master taskloop' | 'master taskloop simd' | 'parallel master 2461 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target 2462 /// enter data' | 'target exit data' | 'target parallel' | 'target 2463 /// parallel for' | 'target update' | 'distribute parallel for' | 2464 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel 2465 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute 2466 /// simd' | 'teams distribute parallel for simd' | 'teams distribute 2467 /// parallel for' | 'target teams' | 'target teams distribute' | 'target 2468 /// teams distribute parallel for' | 'target teams distribute parallel 2469 /// for simd' | 'target teams distribute simd' | 'masked' {clause} 2470 /// annot_pragma_openmp_end 2471 /// 2472 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( 2473 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) { 2474 if (!ReadDirectiveWithinMetadirective) 2475 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && 2476 "Not an OpenMP directive!"); 2477 ParsingOpenMPDirectiveRAII DirScope(*this); 2478 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2479 SmallVector<OMPClause *, 5> Clauses; 2480 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2481 llvm::omp::Clause_enumSize + 1> 2482 FirstClauses(llvm::omp::Clause_enumSize + 1); 2483 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 2484 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 2485 SourceLocation Loc = ReadDirectiveWithinMetadirective 2486 ? Tok.getLocation() 2487 : ConsumeAnnotationToken(), 2488 EndLoc; 2489 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 2490 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) { 2491 Diag(Tok, diag::err_omp_unknown_directive); 2492 return StmtError(); 2493 } 2494 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 2495 // Name of critical directive. 2496 DeclarationNameInfo DirName; 2497 StmtResult Directive = StmtError(); 2498 bool HasAssociatedStatement = true; 2499 2500 switch (DKind) { 2501 case OMPD_nothing: 2502 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2503 ParsedStmtContext()) 2504 Diag(Tok, diag::err_omp_immediate_directive) 2505 << getOpenMPDirectiveName(DKind) << 0; 2506 ConsumeToken(); 2507 skipUntilPragmaOpenMPEnd(DKind); 2508 if (Tok.is(tok::annot_pragma_openmp_end)) 2509 ConsumeAnnotationToken(); 2510 break; 2511 case OMPD_metadirective: { 2512 ConsumeToken(); 2513 SmallVector<VariantMatchInfo, 4> VMIs; 2514 2515 // First iteration of parsing all clauses of metadirective. 2516 // This iteration only parses and collects all context selector ignoring the 2517 // associated directives. 2518 TentativeParsingAction TPA(*this); 2519 ASTContext &ASTContext = Actions.getASTContext(); 2520 2521 BalancedDelimiterTracker T(*this, tok::l_paren, 2522 tok::annot_pragma_openmp_end); 2523 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2524 OpenMPClauseKind CKind = Tok.isAnnotation() 2525 ? OMPC_unknown 2526 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2527 SourceLocation Loc = ConsumeToken(); 2528 2529 // Parse '('. 2530 if (T.expectAndConsume(diag::err_expected_lparen_after, 2531 getOpenMPClauseName(CKind).data())) 2532 return Directive; 2533 2534 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 2535 if (CKind == OMPC_when) { 2536 // parse and get OMPTraitInfo to pass to the When clause 2537 parseOMPContextSelectors(Loc, TI); 2538 if (TI.Sets.size() == 0) { 2539 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause"; 2540 TPA.Commit(); 2541 return Directive; 2542 } 2543 2544 // Parse ':' 2545 if (Tok.is(tok::colon)) 2546 ConsumeAnyToken(); 2547 else { 2548 Diag(Tok, diag::err_omp_expected_colon) << "when clause"; 2549 TPA.Commit(); 2550 return Directive; 2551 } 2552 } 2553 // Skip Directive for now. We will parse directive in the second iteration 2554 int paren = 0; 2555 while (Tok.isNot(tok::r_paren) || paren != 0) { 2556 if (Tok.is(tok::l_paren)) 2557 paren++; 2558 if (Tok.is(tok::r_paren)) 2559 paren--; 2560 if (Tok.is(tok::annot_pragma_openmp_end)) { 2561 Diag(Tok, diag::err_omp_expected_punc) 2562 << getOpenMPClauseName(CKind) << 0; 2563 TPA.Commit(); 2564 return Directive; 2565 } 2566 ConsumeAnyToken(); 2567 } 2568 // Parse ')' 2569 if (Tok.is(tok::r_paren)) 2570 T.consumeClose(); 2571 2572 VariantMatchInfo VMI; 2573 TI.getAsVariantMatchInfo(ASTContext, VMI); 2574 2575 VMIs.push_back(VMI); 2576 } 2577 2578 TPA.Revert(); 2579 // End of the first iteration. Parser is reset to the start of metadirective 2580 2581 std::function<void(StringRef)> DiagUnknownTrait = 2582 [this, Loc](StringRef ISATrait) { 2583 // TODO Track the selector locations in a way that is accessible here 2584 // to improve the diagnostic location. 2585 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; 2586 }; 2587 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait), 2588 /* CurrentFunctionDecl */ nullptr, 2589 ArrayRef<llvm::omp::TraitProperty>()); 2590 2591 // A single match is returned for OpenMP 5.0 2592 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx); 2593 2594 int Idx = 0; 2595 // In OpenMP 5.0 metadirective is either replaced by another directive or 2596 // ignored. 2597 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches 2598 // found by getBestWhenMatchForContext. 2599 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2600 // OpenMP 5.0 implementation - Skip to the best index found. 2601 if (Idx++ != BestIdx) { 2602 ConsumeToken(); // Consume clause name 2603 T.consumeOpen(); // Consume '(' 2604 int paren = 0; 2605 // Skip everything inside the clause 2606 while (Tok.isNot(tok::r_paren) || paren != 0) { 2607 if (Tok.is(tok::l_paren)) 2608 paren++; 2609 if (Tok.is(tok::r_paren)) 2610 paren--; 2611 ConsumeAnyToken(); 2612 } 2613 // Parse ')' 2614 if (Tok.is(tok::r_paren)) 2615 T.consumeClose(); 2616 continue; 2617 } 2618 2619 OpenMPClauseKind CKind = Tok.isAnnotation() 2620 ? OMPC_unknown 2621 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2622 SourceLocation Loc = ConsumeToken(); 2623 2624 // Parse '('. 2625 T.consumeOpen(); 2626 2627 // Skip ContextSelectors for when clause 2628 if (CKind == OMPC_when) { 2629 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 2630 // parse and skip the ContextSelectors 2631 parseOMPContextSelectors(Loc, TI); 2632 2633 // Parse ':' 2634 ConsumeAnyToken(); 2635 } 2636 2637 // If no directive is passed, skip in OpenMP 5.0. 2638 // TODO: Generate nothing directive from OpenMP 5.1. 2639 if (Tok.is(tok::r_paren)) { 2640 SkipUntil(tok::annot_pragma_openmp_end); 2641 break; 2642 } 2643 2644 // Parse Directive 2645 Directive = ParseOpenMPDeclarativeOrExecutableDirective( 2646 StmtCtx, 2647 /*ReadDirectiveWithinMetadirective=*/true); 2648 break; 2649 } 2650 break; 2651 } 2652 case OMPD_threadprivate: { 2653 // FIXME: Should this be permitted in C++? 2654 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2655 ParsedStmtContext()) { 2656 Diag(Tok, diag::err_omp_immediate_directive) 2657 << getOpenMPDirectiveName(DKind) << 0; 2658 } 2659 ConsumeToken(); 2660 DeclDirectiveListParserHelper Helper(this, DKind); 2661 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2662 /*AllowScopeSpecifier=*/false)) { 2663 skipUntilPragmaOpenMPEnd(DKind); 2664 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 2665 Loc, Helper.getIdentifiers()); 2666 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2667 } 2668 SkipUntil(tok::annot_pragma_openmp_end); 2669 break; 2670 } 2671 case OMPD_allocate: { 2672 // FIXME: Should this be permitted in C++? 2673 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2674 ParsedStmtContext()) { 2675 Diag(Tok, diag::err_omp_immediate_directive) 2676 << getOpenMPDirectiveName(DKind) << 0; 2677 } 2678 ConsumeToken(); 2679 DeclDirectiveListParserHelper Helper(this, DKind); 2680 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2681 /*AllowScopeSpecifier=*/false)) { 2682 SmallVector<OMPClause *, 1> Clauses; 2683 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2684 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2685 llvm::omp::Clause_enumSize + 1> 2686 FirstClauses(llvm::omp::Clause_enumSize + 1); 2687 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2688 OpenMPClauseKind CKind = 2689 Tok.isAnnotation() ? OMPC_unknown 2690 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2691 Actions.StartOpenMPClause(CKind); 2692 OMPClause *Clause = ParseOpenMPClause( 2693 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2694 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2695 StopBeforeMatch); 2696 FirstClauses[unsigned(CKind)].setInt(true); 2697 if (Clause != nullptr) 2698 Clauses.push_back(Clause); 2699 if (Tok.is(tok::annot_pragma_openmp_end)) { 2700 Actions.EndOpenMPClause(); 2701 break; 2702 } 2703 // Skip ',' if any. 2704 if (Tok.is(tok::comma)) 2705 ConsumeToken(); 2706 Actions.EndOpenMPClause(); 2707 } 2708 skipUntilPragmaOpenMPEnd(DKind); 2709 } 2710 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 2711 Loc, Helper.getIdentifiers(), Clauses); 2712 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2713 } 2714 SkipUntil(tok::annot_pragma_openmp_end); 2715 break; 2716 } 2717 case OMPD_declare_reduction: 2718 ConsumeToken(); 2719 if (DeclGroupPtrTy Res = 2720 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 2721 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2722 ConsumeAnyToken(); 2723 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2724 } else { 2725 SkipUntil(tok::annot_pragma_openmp_end); 2726 } 2727 break; 2728 case OMPD_declare_mapper: { 2729 ConsumeToken(); 2730 if (DeclGroupPtrTy Res = 2731 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 2732 // Skip the last annot_pragma_openmp_end. 2733 ConsumeAnnotationToken(); 2734 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2735 } else { 2736 SkipUntil(tok::annot_pragma_openmp_end); 2737 } 2738 break; 2739 } 2740 case OMPD_flush: 2741 case OMPD_depobj: 2742 case OMPD_scan: 2743 case OMPD_taskyield: 2744 case OMPD_barrier: 2745 case OMPD_taskwait: 2746 case OMPD_cancellation_point: 2747 case OMPD_cancel: 2748 case OMPD_target_enter_data: 2749 case OMPD_target_exit_data: 2750 case OMPD_target_update: 2751 case OMPD_interop: 2752 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2753 ParsedStmtContext()) { 2754 Diag(Tok, diag::err_omp_immediate_directive) 2755 << getOpenMPDirectiveName(DKind) << 0; 2756 } 2757 HasAssociatedStatement = false; 2758 // Fall through for further analysis. 2759 LLVM_FALLTHROUGH; 2760 case OMPD_parallel: 2761 case OMPD_simd: 2762 case OMPD_tile: 2763 case OMPD_unroll: 2764 case OMPD_for: 2765 case OMPD_for_simd: 2766 case OMPD_sections: 2767 case OMPD_single: 2768 case OMPD_section: 2769 case OMPD_master: 2770 case OMPD_critical: 2771 case OMPD_parallel_for: 2772 case OMPD_parallel_for_simd: 2773 case OMPD_parallel_sections: 2774 case OMPD_parallel_master: 2775 case OMPD_parallel_masked: 2776 case OMPD_task: 2777 case OMPD_ordered: 2778 case OMPD_atomic: 2779 case OMPD_target: 2780 case OMPD_teams: 2781 case OMPD_taskgroup: 2782 case OMPD_target_data: 2783 case OMPD_target_parallel: 2784 case OMPD_target_parallel_for: 2785 case OMPD_loop: 2786 case OMPD_teams_loop: 2787 case OMPD_target_teams_loop: 2788 case OMPD_parallel_loop: 2789 case OMPD_target_parallel_loop: 2790 case OMPD_taskloop: 2791 case OMPD_taskloop_simd: 2792 case OMPD_master_taskloop: 2793 case OMPD_masked_taskloop: 2794 case OMPD_master_taskloop_simd: 2795 case OMPD_masked_taskloop_simd: 2796 case OMPD_parallel_master_taskloop: 2797 case OMPD_parallel_master_taskloop_simd: 2798 case OMPD_distribute: 2799 case OMPD_distribute_parallel_for: 2800 case OMPD_distribute_parallel_for_simd: 2801 case OMPD_distribute_simd: 2802 case OMPD_target_parallel_for_simd: 2803 case OMPD_target_simd: 2804 case OMPD_teams_distribute: 2805 case OMPD_teams_distribute_simd: 2806 case OMPD_teams_distribute_parallel_for_simd: 2807 case OMPD_teams_distribute_parallel_for: 2808 case OMPD_target_teams: 2809 case OMPD_target_teams_distribute: 2810 case OMPD_target_teams_distribute_parallel_for: 2811 case OMPD_target_teams_distribute_parallel_for_simd: 2812 case OMPD_target_teams_distribute_simd: 2813 case OMPD_dispatch: 2814 case OMPD_masked: { 2815 // Special processing for flush and depobj clauses. 2816 Token ImplicitTok; 2817 bool ImplicitClauseAllowed = false; 2818 if (DKind == OMPD_flush || DKind == OMPD_depobj) { 2819 ImplicitTok = Tok; 2820 ImplicitClauseAllowed = true; 2821 } 2822 ConsumeToken(); 2823 // Parse directive name of the 'critical' directive if any. 2824 if (DKind == OMPD_critical) { 2825 BalancedDelimiterTracker T(*this, tok::l_paren, 2826 tok::annot_pragma_openmp_end); 2827 if (!T.consumeOpen()) { 2828 if (Tok.isAnyIdentifier()) { 2829 DirName = 2830 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 2831 ConsumeAnyToken(); 2832 } else { 2833 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 2834 } 2835 T.consumeClose(); 2836 } 2837 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 2838 CancelRegion = parseOpenMPDirectiveKind(*this); 2839 if (Tok.isNot(tok::annot_pragma_openmp_end)) 2840 ConsumeToken(); 2841 } 2842 2843 if (isOpenMPLoopDirective(DKind)) 2844 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 2845 if (isOpenMPSimdDirective(DKind)) 2846 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 2847 ParseScope OMPDirectiveScope(this, ScopeFlags); 2848 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 2849 2850 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2851 // If we are parsing for a directive within a metadirective, the directive 2852 // ends with a ')'. 2853 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) { 2854 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2855 ConsumeAnyToken(); 2856 break; 2857 } 2858 bool HasImplicitClause = false; 2859 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { 2860 HasImplicitClause = true; 2861 // Push copy of the current token back to stream to properly parse 2862 // pseudo-clause OMPFlushClause or OMPDepobjClause. 2863 PP.EnterToken(Tok, /*IsReinject*/ true); 2864 PP.EnterToken(ImplicitTok, /*IsReinject*/ true); 2865 ConsumeAnyToken(); 2866 } 2867 OpenMPClauseKind CKind = Tok.isAnnotation() 2868 ? OMPC_unknown 2869 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2870 if (HasImplicitClause) { 2871 assert(CKind == OMPC_unknown && "Must be unknown implicit clause."); 2872 if (DKind == OMPD_flush) { 2873 CKind = OMPC_flush; 2874 } else { 2875 assert(DKind == OMPD_depobj && 2876 "Expected flush or depobj directives."); 2877 CKind = OMPC_depobj; 2878 } 2879 } 2880 // No more implicit clauses allowed. 2881 ImplicitClauseAllowed = false; 2882 Actions.StartOpenMPClause(CKind); 2883 HasImplicitClause = false; 2884 OMPClause *Clause = ParseOpenMPClause( 2885 DKind, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2886 FirstClauses[unsigned(CKind)].setInt(true); 2887 if (Clause) { 2888 FirstClauses[unsigned(CKind)].setPointer(Clause); 2889 Clauses.push_back(Clause); 2890 } 2891 2892 // Skip ',' if any. 2893 if (Tok.is(tok::comma)) 2894 ConsumeToken(); 2895 Actions.EndOpenMPClause(); 2896 } 2897 // End location of the directive. 2898 EndLoc = Tok.getLocation(); 2899 // Consume final annot_pragma_openmp_end. 2900 ConsumeAnnotationToken(); 2901 2902 // OpenMP [2.13.8, ordered Construct, Syntax] 2903 // If the depend clause is specified, the ordered construct is a stand-alone 2904 // directive. 2905 if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) { 2906 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2907 ParsedStmtContext()) { 2908 Diag(Loc, diag::err_omp_immediate_directive) 2909 << getOpenMPDirectiveName(DKind) << 1 2910 << getOpenMPClauseName(OMPC_depend); 2911 } 2912 HasAssociatedStatement = false; 2913 } 2914 2915 if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) { 2916 Diag(Loc, diag::err_omp_required_clause) 2917 << getOpenMPDirectiveName(OMPD_tile) << "sizes"; 2918 } 2919 2920 StmtResult AssociatedStmt; 2921 if (HasAssociatedStatement) { 2922 // The body is a block scope like in Lambdas and Blocks. 2923 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2924 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 2925 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 2926 // should have at least one compound statement scope within it. 2927 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2928 { 2929 Sema::CompoundScopeRAII Scope(Actions); 2930 AssociatedStmt = ParseStatement(); 2931 2932 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) && 2933 getLangOpts().OpenMPIRBuilder) 2934 AssociatedStmt = Actions.ActOnOpenMPLoopnest(AssociatedStmt.get()); 2935 } 2936 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2937 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 2938 DKind == OMPD_target_exit_data) { 2939 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2940 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 2941 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 2942 /*isStmtExpr=*/false)); 2943 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2944 } 2945 Directive = Actions.ActOnOpenMPExecutableDirective( 2946 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 2947 EndLoc); 2948 2949 // Exit scope. 2950 Actions.EndOpenMPDSABlock(Directive.get()); 2951 OMPDirectiveScope.Exit(); 2952 break; 2953 } 2954 case OMPD_declare_simd: 2955 case OMPD_declare_target: 2956 case OMPD_begin_declare_target: 2957 case OMPD_end_declare_target: 2958 case OMPD_requires: 2959 case OMPD_begin_declare_variant: 2960 case OMPD_end_declare_variant: 2961 case OMPD_declare_variant: 2962 Diag(Tok, diag::err_omp_unexpected_directive) 2963 << 1 << getOpenMPDirectiveName(DKind); 2964 SkipUntil(tok::annot_pragma_openmp_end); 2965 break; 2966 case OMPD_unknown: 2967 default: 2968 Diag(Tok, diag::err_omp_unknown_directive); 2969 SkipUntil(tok::annot_pragma_openmp_end); 2970 break; 2971 } 2972 return Directive; 2973 } 2974 2975 // Parses simple list: 2976 // simple-variable-list: 2977 // '(' id-expression {, id-expression} ')' 2978 // 2979 bool Parser::ParseOpenMPSimpleVarList( 2980 OpenMPDirectiveKind Kind, 2981 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> 2982 &Callback, 2983 bool AllowScopeSpecifier) { 2984 // Parse '('. 2985 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2986 if (T.expectAndConsume(diag::err_expected_lparen_after, 2987 getOpenMPDirectiveName(Kind).data())) 2988 return true; 2989 bool IsCorrect = true; 2990 bool NoIdentIsFound = true; 2991 2992 // Read tokens while ')' or annot_pragma_openmp_end is not found. 2993 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 2994 CXXScopeSpec SS; 2995 UnqualifiedId Name; 2996 // Read var name. 2997 Token PrevTok = Tok; 2998 NoIdentIsFound = false; 2999 3000 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 3001 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 3002 /*ObjectHasErrors=*/false, false)) { 3003 IsCorrect = false; 3004 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3005 StopBeforeMatch); 3006 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, 3007 /*ObjectHadErrors=*/false, false, false, 3008 false, false, nullptr, Name)) { 3009 IsCorrect = false; 3010 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3011 StopBeforeMatch); 3012 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 3013 Tok.isNot(tok::annot_pragma_openmp_end)) { 3014 IsCorrect = false; 3015 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3016 StopBeforeMatch); 3017 Diag(PrevTok.getLocation(), diag::err_expected) 3018 << tok::identifier 3019 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 3020 } else { 3021 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 3022 } 3023 // Consume ','. 3024 if (Tok.is(tok::comma)) { 3025 ConsumeToken(); 3026 } 3027 } 3028 3029 if (NoIdentIsFound) { 3030 Diag(Tok, diag::err_expected) << tok::identifier; 3031 IsCorrect = false; 3032 } 3033 3034 // Parse ')'. 3035 IsCorrect = !T.consumeClose() && IsCorrect; 3036 3037 return !IsCorrect; 3038 } 3039 3040 OMPClause *Parser::ParseOpenMPSizesClause() { 3041 SourceLocation ClauseNameLoc = ConsumeToken(); 3042 SmallVector<Expr *, 4> ValExprs; 3043 3044 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3045 if (T.consumeOpen()) { 3046 Diag(Tok, diag::err_expected) << tok::l_paren; 3047 return nullptr; 3048 } 3049 3050 while (true) { 3051 ExprResult Val = ParseConstantExpression(); 3052 if (!Val.isUsable()) { 3053 T.skipToEnd(); 3054 return nullptr; 3055 } 3056 3057 ValExprs.push_back(Val.get()); 3058 3059 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end)) 3060 break; 3061 3062 ExpectAndConsume(tok::comma); 3063 } 3064 3065 T.consumeClose(); 3066 3067 return Actions.ActOnOpenMPSizesClause( 3068 ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation()); 3069 } 3070 3071 OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { 3072 SourceLocation Loc = Tok.getLocation(); 3073 ConsumeAnyToken(); 3074 3075 // Parse '('. 3076 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3077 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator")) 3078 return nullptr; 3079 SmallVector<Sema::UsesAllocatorsData, 4> Data; 3080 do { 3081 ExprResult Allocator = 3082 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression(); 3083 if (Allocator.isInvalid()) { 3084 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3085 StopBeforeMatch); 3086 break; 3087 } 3088 Sema::UsesAllocatorsData &D = Data.emplace_back(); 3089 D.Allocator = Allocator.get(); 3090 if (Tok.is(tok::l_paren)) { 3091 BalancedDelimiterTracker T(*this, tok::l_paren, 3092 tok::annot_pragma_openmp_end); 3093 T.consumeOpen(); 3094 ExprResult AllocatorTraits = 3095 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression(); 3096 T.consumeClose(); 3097 if (AllocatorTraits.isInvalid()) { 3098 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3099 StopBeforeMatch); 3100 break; 3101 } 3102 D.AllocatorTraits = AllocatorTraits.get(); 3103 D.LParenLoc = T.getOpenLocation(); 3104 D.RParenLoc = T.getCloseLocation(); 3105 } 3106 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 3107 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0; 3108 // Parse ',' 3109 if (Tok.is(tok::comma)) 3110 ConsumeAnyToken(); 3111 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); 3112 T.consumeClose(); 3113 return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(), 3114 T.getCloseLocation(), Data); 3115 } 3116 3117 /// Parsing of OpenMP clauses. 3118 /// 3119 /// clause: 3120 /// if-clause | final-clause | num_threads-clause | safelen-clause | 3121 /// default-clause | private-clause | firstprivate-clause | shared-clause 3122 /// | linear-clause | aligned-clause | collapse-clause | bind-clause | 3123 /// lastprivate-clause | reduction-clause | proc_bind-clause | 3124 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 3125 /// mergeable-clause | flush-clause | read-clause | write-clause | 3126 /// update-clause | capture-clause | seq_cst-clause | device-clause | 3127 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 3128 /// thread_limit-clause | priority-clause | grainsize-clause | 3129 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 3130 /// from-clause | is_device_ptr-clause | task_reduction-clause | 3131 /// in_reduction-clause | allocator-clause | allocate-clause | 3132 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | 3133 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause | 3134 /// exclusive-clause | uses_allocators-clause | use_device_addr-clause | 3135 /// has_device_addr 3136 /// 3137 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 3138 OpenMPClauseKind CKind, bool FirstClause) { 3139 OMPClauseKind = CKind; 3140 OMPClause *Clause = nullptr; 3141 bool ErrorFound = false; 3142 bool WrongDirective = false; 3143 // Check if clause is allowed for the given directive. 3144 if (CKind != OMPC_unknown && 3145 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 3146 Diag(Tok, diag::err_omp_unexpected_clause) 3147 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 3148 ErrorFound = true; 3149 WrongDirective = true; 3150 } 3151 3152 switch (CKind) { 3153 case OMPC_final: 3154 case OMPC_num_threads: 3155 case OMPC_safelen: 3156 case OMPC_simdlen: 3157 case OMPC_collapse: 3158 case OMPC_ordered: 3159 case OMPC_num_teams: 3160 case OMPC_thread_limit: 3161 case OMPC_priority: 3162 case OMPC_grainsize: 3163 case OMPC_num_tasks: 3164 case OMPC_hint: 3165 case OMPC_allocator: 3166 case OMPC_depobj: 3167 case OMPC_detach: 3168 case OMPC_novariants: 3169 case OMPC_nocontext: 3170 case OMPC_filter: 3171 case OMPC_partial: 3172 case OMPC_align: 3173 // OpenMP [2.5, Restrictions] 3174 // At most one num_threads clause can appear on the directive. 3175 // OpenMP [2.8.1, simd construct, Restrictions] 3176 // Only one safelen clause can appear on a simd directive. 3177 // Only one simdlen clause can appear on a simd directive. 3178 // Only one collapse clause can appear on a simd directive. 3179 // OpenMP [2.11.1, task Construct, Restrictions] 3180 // At most one if clause can appear on the directive. 3181 // At most one final clause can appear on the directive. 3182 // OpenMP [teams Construct, Restrictions] 3183 // At most one num_teams clause can appear on the directive. 3184 // At most one thread_limit clause can appear on the directive. 3185 // OpenMP [2.9.1, task Construct, Restrictions] 3186 // At most one priority clause can appear on the directive. 3187 // OpenMP [2.9.2, taskloop Construct, Restrictions] 3188 // At most one grainsize clause can appear on the directive. 3189 // OpenMP [2.9.2, taskloop Construct, Restrictions] 3190 // At most one num_tasks clause can appear on the directive. 3191 // OpenMP [2.11.3, allocate Directive, Restrictions] 3192 // At most one allocator clause can appear on the directive. 3193 // OpenMP 5.0, 2.10.1 task Construct, Restrictions. 3194 // At most one detach clause can appear on the directive. 3195 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions. 3196 // At most one novariants clause can appear on a dispatch directive. 3197 // At most one nocontext clause can appear on a dispatch directive. 3198 if (!FirstClause) { 3199 Diag(Tok, diag::err_omp_more_one_clause) 3200 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3201 ErrorFound = true; 3202 } 3203 3204 if ((CKind == OMPC_ordered || CKind == OMPC_partial) && 3205 PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 3206 Clause = ParseOpenMPClause(CKind, WrongDirective); 3207 else 3208 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 3209 break; 3210 case OMPC_default: 3211 case OMPC_proc_bind: 3212 case OMPC_atomic_default_mem_order: 3213 case OMPC_order: 3214 case OMPC_bind: 3215 // OpenMP [2.14.3.1, Restrictions] 3216 // Only a single default clause may be specified on a parallel, task or 3217 // teams directive. 3218 // OpenMP [2.5, parallel Construct, Restrictions] 3219 // At most one proc_bind clause can appear on the directive. 3220 // OpenMP [5.0, Requires directive, Restrictions] 3221 // At most one atomic_default_mem_order clause can appear 3222 // on the directive 3223 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions. 3224 // At most one bind clause can appear on a loop directive. 3225 if (!FirstClause && CKind != OMPC_order) { 3226 Diag(Tok, diag::err_omp_more_one_clause) 3227 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3228 ErrorFound = true; 3229 } 3230 3231 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 3232 break; 3233 case OMPC_device: 3234 case OMPC_schedule: 3235 case OMPC_dist_schedule: 3236 case OMPC_defaultmap: 3237 // OpenMP [2.7.1, Restrictions, p. 3] 3238 // Only one schedule clause can appear on a loop directive. 3239 // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 3240 // At most one defaultmap clause can appear on the directive. 3241 // OpenMP 5.0 [2.12.5, target construct, Restrictions] 3242 // At most one device clause can appear on the directive. 3243 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 3244 !FirstClause) { 3245 Diag(Tok, diag::err_omp_more_one_clause) 3246 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3247 ErrorFound = true; 3248 } 3249 LLVM_FALLTHROUGH; 3250 case OMPC_if: 3251 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); 3252 break; 3253 case OMPC_nowait: 3254 case OMPC_untied: 3255 case OMPC_mergeable: 3256 case OMPC_read: 3257 case OMPC_write: 3258 case OMPC_capture: 3259 case OMPC_compare: 3260 case OMPC_seq_cst: 3261 case OMPC_acq_rel: 3262 case OMPC_acquire: 3263 case OMPC_release: 3264 case OMPC_relaxed: 3265 case OMPC_threads: 3266 case OMPC_simd: 3267 case OMPC_nogroup: 3268 case OMPC_unified_address: 3269 case OMPC_unified_shared_memory: 3270 case OMPC_reverse_offload: 3271 case OMPC_dynamic_allocators: 3272 case OMPC_full: 3273 // OpenMP [2.7.1, Restrictions, p. 9] 3274 // Only one ordered clause can appear on a loop directive. 3275 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 3276 // Only one nowait clause can appear on a for directive. 3277 // OpenMP [5.0, Requires directive, Restrictions] 3278 // Each of the requires clauses can appear at most once on the directive. 3279 if (!FirstClause) { 3280 Diag(Tok, diag::err_omp_more_one_clause) 3281 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3282 ErrorFound = true; 3283 } 3284 3285 Clause = ParseOpenMPClause(CKind, WrongDirective); 3286 break; 3287 case OMPC_update: 3288 if (!FirstClause) { 3289 Diag(Tok, diag::err_omp_more_one_clause) 3290 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3291 ErrorFound = true; 3292 } 3293 3294 Clause = (DKind == OMPD_depobj) 3295 ? ParseOpenMPSimpleClause(CKind, WrongDirective) 3296 : ParseOpenMPClause(CKind, WrongDirective); 3297 break; 3298 case OMPC_private: 3299 case OMPC_firstprivate: 3300 case OMPC_lastprivate: 3301 case OMPC_shared: 3302 case OMPC_reduction: 3303 case OMPC_task_reduction: 3304 case OMPC_in_reduction: 3305 case OMPC_linear: 3306 case OMPC_aligned: 3307 case OMPC_copyin: 3308 case OMPC_copyprivate: 3309 case OMPC_flush: 3310 case OMPC_depend: 3311 case OMPC_map: 3312 case OMPC_to: 3313 case OMPC_from: 3314 case OMPC_use_device_ptr: 3315 case OMPC_use_device_addr: 3316 case OMPC_is_device_ptr: 3317 case OMPC_has_device_addr: 3318 case OMPC_allocate: 3319 case OMPC_nontemporal: 3320 case OMPC_inclusive: 3321 case OMPC_exclusive: 3322 case OMPC_affinity: 3323 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 3324 break; 3325 case OMPC_sizes: 3326 if (!FirstClause) { 3327 Diag(Tok, diag::err_omp_more_one_clause) 3328 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3329 ErrorFound = true; 3330 } 3331 3332 Clause = ParseOpenMPSizesClause(); 3333 break; 3334 case OMPC_uses_allocators: 3335 Clause = ParseOpenMPUsesAllocatorClause(DKind); 3336 break; 3337 case OMPC_destroy: 3338 if (DKind != OMPD_interop) { 3339 if (!FirstClause) { 3340 Diag(Tok, diag::err_omp_more_one_clause) 3341 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3342 ErrorFound = true; 3343 } 3344 Clause = ParseOpenMPClause(CKind, WrongDirective); 3345 break; 3346 } 3347 LLVM_FALLTHROUGH; 3348 case OMPC_init: 3349 case OMPC_use: 3350 Clause = ParseOpenMPInteropClause(CKind, WrongDirective); 3351 break; 3352 case OMPC_device_type: 3353 case OMPC_unknown: 3354 skipUntilPragmaOpenMPEnd(DKind); 3355 break; 3356 case OMPC_threadprivate: 3357 case OMPC_uniform: 3358 case OMPC_match: 3359 if (!WrongDirective) 3360 Diag(Tok, diag::err_omp_unexpected_clause) 3361 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 3362 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 3363 break; 3364 default: 3365 break; 3366 } 3367 return ErrorFound ? nullptr : Clause; 3368 } 3369 3370 /// Parses simple expression in parens for single-expression clauses of OpenMP 3371 /// constructs. 3372 /// \param RLoc Returned location of right paren. 3373 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 3374 SourceLocation &RLoc, 3375 bool IsAddressOfOperand) { 3376 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3377 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 3378 return ExprError(); 3379 3380 SourceLocation ELoc = Tok.getLocation(); 3381 ExprResult LHS( 3382 ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast)); 3383 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3384 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3385 3386 // Parse ')'. 3387 RLoc = Tok.getLocation(); 3388 if (!T.consumeClose()) 3389 RLoc = T.getCloseLocation(); 3390 3391 return Val; 3392 } 3393 3394 /// Parsing of OpenMP clauses with single expressions like 'final', 3395 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 3396 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or 3397 /// 'detach'. 3398 /// 3399 /// final-clause: 3400 /// 'final' '(' expression ')' 3401 /// 3402 /// num_threads-clause: 3403 /// 'num_threads' '(' expression ')' 3404 /// 3405 /// safelen-clause: 3406 /// 'safelen' '(' expression ')' 3407 /// 3408 /// simdlen-clause: 3409 /// 'simdlen' '(' expression ')' 3410 /// 3411 /// collapse-clause: 3412 /// 'collapse' '(' expression ')' 3413 /// 3414 /// priority-clause: 3415 /// 'priority' '(' expression ')' 3416 /// 3417 /// grainsize-clause: 3418 /// 'grainsize' '(' expression ')' 3419 /// 3420 /// num_tasks-clause: 3421 /// 'num_tasks' '(' expression ')' 3422 /// 3423 /// hint-clause: 3424 /// 'hint' '(' expression ')' 3425 /// 3426 /// allocator-clause: 3427 /// 'allocator' '(' expression ')' 3428 /// 3429 /// detach-clause: 3430 /// 'detach' '(' event-handler-expression ')' 3431 /// 3432 /// align-clause 3433 /// 'align' '(' positive-integer-constant ')' 3434 /// 3435 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 3436 bool ParseOnly) { 3437 SourceLocation Loc = ConsumeToken(); 3438 SourceLocation LLoc = Tok.getLocation(); 3439 SourceLocation RLoc; 3440 3441 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 3442 3443 if (Val.isInvalid()) 3444 return nullptr; 3445 3446 if (ParseOnly) 3447 return nullptr; 3448 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 3449 } 3450 3451 /// Parse indirect clause for '#pragma omp declare target' directive. 3452 /// 'indirect' '[' '(' invoked-by-fptr ')' ']' 3453 /// where invoked-by-fptr is a constant boolean expression that evaluates to 3454 /// true or false at compile time. 3455 bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI, 3456 bool ParseOnly) { 3457 SourceLocation Loc = ConsumeToken(); 3458 SourceLocation RLoc; 3459 3460 if (Tok.isNot(tok::l_paren)) { 3461 if (ParseOnly) 3462 return false; 3463 DTCI.Indirect = nullptr; 3464 return true; 3465 } 3466 3467 ExprResult Val = 3468 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc); 3469 if (Val.isInvalid()) 3470 return false; 3471 3472 if (ParseOnly) 3473 return false; 3474 3475 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() && 3476 !Val.get()->isInstantiationDependent() && 3477 !Val.get()->containsUnexpandedParameterPack()) { 3478 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get()); 3479 if (Ret.isInvalid()) 3480 return false; 3481 llvm::APSInt Result; 3482 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result, 3483 Sema::AllowFold); 3484 if (Ret.isInvalid()) 3485 return false; 3486 DTCI.Indirect = Val.get(); 3487 return true; 3488 } 3489 return false; 3490 } 3491 3492 /// Parsing of OpenMP clauses that use an interop-var. 3493 /// 3494 /// init-clause: 3495 /// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var) 3496 /// 3497 /// destroy-clause: 3498 /// destroy(interop-var) 3499 /// 3500 /// use-clause: 3501 /// use(interop-var) 3502 /// 3503 /// interop-modifier: 3504 /// prefer_type(preference-list) 3505 /// 3506 /// preference-list: 3507 /// foreign-runtime-id [, foreign-runtime-id]... 3508 /// 3509 /// foreign-runtime-id: 3510 /// <string-literal> | <constant-integral-expression> 3511 /// 3512 /// interop-type: 3513 /// target | targetsync 3514 /// 3515 OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind, 3516 bool ParseOnly) { 3517 SourceLocation Loc = ConsumeToken(); 3518 // Parse '('. 3519 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3520 if (T.expectAndConsume(diag::err_expected_lparen_after, 3521 getOpenMPClauseName(Kind).data())) 3522 return nullptr; 3523 3524 bool IsTarget = false; 3525 bool IsTargetSync = false; 3526 SmallVector<Expr *, 4> Prefs; 3527 3528 if (Kind == OMPC_init) { 3529 3530 // Parse optional interop-modifier. 3531 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "prefer_type") { 3532 ConsumeToken(); 3533 BalancedDelimiterTracker PT(*this, tok::l_paren, 3534 tok::annot_pragma_openmp_end); 3535 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type")) 3536 return nullptr; 3537 3538 while (Tok.isNot(tok::r_paren)) { 3539 SourceLocation Loc = Tok.getLocation(); 3540 ExprResult LHS = ParseCastExpression(AnyCastExpr); 3541 ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr( 3542 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3543 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc, 3544 /*DiscardedValue=*/false); 3545 if (PTExpr.isUsable()) 3546 Prefs.push_back(PTExpr.get()); 3547 else 3548 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3549 StopBeforeMatch); 3550 3551 if (Tok.is(tok::comma)) 3552 ConsumeToken(); 3553 } 3554 PT.consumeClose(); 3555 } 3556 3557 if (!Prefs.empty()) { 3558 if (Tok.is(tok::comma)) 3559 ConsumeToken(); 3560 else 3561 Diag(Tok, diag::err_omp_expected_punc_after_interop_mod); 3562 } 3563 3564 // Parse the interop-types. 3565 if (Optional<OMPDeclareVariantAttr::InteropType> IType = 3566 parseInteropTypeList(*this)) { 3567 IsTarget = IType != OMPDeclareVariantAttr::TargetSync; 3568 IsTargetSync = IType != OMPDeclareVariantAttr::Target; 3569 if (Tok.isNot(tok::colon)) 3570 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types"; 3571 } 3572 if (Tok.is(tok::colon)) 3573 ConsumeToken(); 3574 } 3575 3576 // Parse the variable. 3577 SourceLocation VarLoc = Tok.getLocation(); 3578 ExprResult InteropVarExpr = 3579 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 3580 if (!InteropVarExpr.isUsable()) { 3581 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3582 StopBeforeMatch); 3583 } 3584 3585 // Parse ')'. 3586 SourceLocation RLoc = Tok.getLocation(); 3587 if (!T.consumeClose()) 3588 RLoc = T.getCloseLocation(); 3589 3590 if (ParseOnly || !InteropVarExpr.isUsable() || 3591 (Kind == OMPC_init && !IsTarget && !IsTargetSync)) 3592 return nullptr; 3593 3594 if (Kind == OMPC_init) 3595 return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget, 3596 IsTargetSync, Loc, T.getOpenLocation(), 3597 VarLoc, RLoc); 3598 if (Kind == OMPC_use) 3599 return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc, 3600 T.getOpenLocation(), VarLoc, RLoc); 3601 3602 if (Kind == OMPC_destroy) 3603 return Actions.ActOnOpenMPDestroyClause(InteropVarExpr.get(), Loc, 3604 T.getOpenLocation(), VarLoc, RLoc); 3605 3606 llvm_unreachable("Unexpected interop variable clause."); 3607 } 3608 3609 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 3610 /// 3611 /// default-clause: 3612 /// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')' 3613 /// 3614 /// proc_bind-clause: 3615 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' 3616 /// 3617 /// bind-clause: 3618 /// 'bind' '(' 'teams' | 'parallel' | 'thread' ')' 3619 /// 3620 /// update-clause: 3621 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' | 3622 /// 'inoutset' ')' 3623 /// 3624 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 3625 bool ParseOnly) { 3626 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 3627 if (!Val || ParseOnly) 3628 return nullptr; 3629 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default && 3630 (static_cast<DefaultKind>(Val.getValue().Type) == OMP_DEFAULT_private || 3631 static_cast<DefaultKind>(Val.getValue().Type) == 3632 OMP_DEFAULT_firstprivate)) { 3633 Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa) 3634 << getOpenMPClauseName(static_cast<DefaultKind>(Val.getValue().Type) == 3635 OMP_DEFAULT_private 3636 ? OMPC_private 3637 : OMPC_firstprivate) 3638 << getOpenMPClauseName(OMPC_default) << "5.1"; 3639 return nullptr; 3640 } 3641 return Actions.ActOnOpenMPSimpleClause( 3642 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, 3643 Val.getValue().Loc, Val.getValue().RLoc); 3644 } 3645 3646 /// Parsing of OpenMP clauses like 'ordered'. 3647 /// 3648 /// ordered-clause: 3649 /// 'ordered' 3650 /// 3651 /// nowait-clause: 3652 /// 'nowait' 3653 /// 3654 /// untied-clause: 3655 /// 'untied' 3656 /// 3657 /// mergeable-clause: 3658 /// 'mergeable' 3659 /// 3660 /// read-clause: 3661 /// 'read' 3662 /// 3663 /// threads-clause: 3664 /// 'threads' 3665 /// 3666 /// simd-clause: 3667 /// 'simd' 3668 /// 3669 /// nogroup-clause: 3670 /// 'nogroup' 3671 /// 3672 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 3673 SourceLocation Loc = Tok.getLocation(); 3674 ConsumeAnyToken(); 3675 3676 if (ParseOnly) 3677 return nullptr; 3678 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 3679 } 3680 3681 /// Parsing of OpenMP clauses with single expressions and some additional 3682 /// argument like 'schedule' or 'dist_schedule'. 3683 /// 3684 /// schedule-clause: 3685 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 3686 /// ')' 3687 /// 3688 /// if-clause: 3689 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 3690 /// 3691 /// defaultmap: 3692 /// 'defaultmap' '(' modifier [ ':' kind ] ')' 3693 /// 3694 /// device-clause: 3695 /// 'device' '(' [ device-modifier ':' ] expression ')' 3696 /// 3697 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, 3698 OpenMPClauseKind Kind, 3699 bool ParseOnly) { 3700 SourceLocation Loc = ConsumeToken(); 3701 SourceLocation DelimLoc; 3702 // Parse '('. 3703 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3704 if (T.expectAndConsume(diag::err_expected_lparen_after, 3705 getOpenMPClauseName(Kind).data())) 3706 return nullptr; 3707 3708 ExprResult Val; 3709 SmallVector<unsigned, 4> Arg; 3710 SmallVector<SourceLocation, 4> KLoc; 3711 if (Kind == OMPC_schedule) { 3712 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 3713 Arg.resize(NumberOfElements); 3714 KLoc.resize(NumberOfElements); 3715 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 3716 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 3717 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 3718 unsigned KindModifier = getOpenMPSimpleClauseType( 3719 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3720 if (KindModifier > OMPC_SCHEDULE_unknown) { 3721 // Parse 'modifier' 3722 Arg[Modifier1] = KindModifier; 3723 KLoc[Modifier1] = Tok.getLocation(); 3724 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3725 Tok.isNot(tok::annot_pragma_openmp_end)) 3726 ConsumeAnyToken(); 3727 if (Tok.is(tok::comma)) { 3728 // Parse ',' 'modifier' 3729 ConsumeAnyToken(); 3730 KindModifier = getOpenMPSimpleClauseType( 3731 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3732 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 3733 ? KindModifier 3734 : (unsigned)OMPC_SCHEDULE_unknown; 3735 KLoc[Modifier2] = Tok.getLocation(); 3736 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3737 Tok.isNot(tok::annot_pragma_openmp_end)) 3738 ConsumeAnyToken(); 3739 } 3740 // Parse ':' 3741 if (Tok.is(tok::colon)) 3742 ConsumeAnyToken(); 3743 else 3744 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 3745 KindModifier = getOpenMPSimpleClauseType( 3746 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3747 } 3748 Arg[ScheduleKind] = KindModifier; 3749 KLoc[ScheduleKind] = Tok.getLocation(); 3750 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3751 Tok.isNot(tok::annot_pragma_openmp_end)) 3752 ConsumeAnyToken(); 3753 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 3754 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 3755 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 3756 Tok.is(tok::comma)) 3757 DelimLoc = ConsumeAnyToken(); 3758 } else if (Kind == OMPC_dist_schedule) { 3759 Arg.push_back(getOpenMPSimpleClauseType( 3760 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3761 KLoc.push_back(Tok.getLocation()); 3762 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3763 Tok.isNot(tok::annot_pragma_openmp_end)) 3764 ConsumeAnyToken(); 3765 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 3766 DelimLoc = ConsumeAnyToken(); 3767 } else if (Kind == OMPC_defaultmap) { 3768 // Get a defaultmap modifier 3769 unsigned Modifier = getOpenMPSimpleClauseType( 3770 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3771 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 3772 // pointer 3773 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 3774 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 3775 Arg.push_back(Modifier); 3776 KLoc.push_back(Tok.getLocation()); 3777 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3778 Tok.isNot(tok::annot_pragma_openmp_end)) 3779 ConsumeAnyToken(); 3780 // Parse ':' 3781 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) { 3782 if (Tok.is(tok::colon)) 3783 ConsumeAnyToken(); 3784 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 3785 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 3786 // Get a defaultmap kind 3787 Arg.push_back(getOpenMPSimpleClauseType( 3788 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3789 KLoc.push_back(Tok.getLocation()); 3790 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3791 Tok.isNot(tok::annot_pragma_openmp_end)) 3792 ConsumeAnyToken(); 3793 } else { 3794 Arg.push_back(OMPC_DEFAULTMAP_unknown); 3795 KLoc.push_back(SourceLocation()); 3796 } 3797 } else if (Kind == OMPC_device) { 3798 // Only target executable directives support extended device construct. 3799 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 && 3800 NextToken().is(tok::colon)) { 3801 // Parse optional <device modifier> ':' 3802 Arg.push_back(getOpenMPSimpleClauseType( 3803 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3804 KLoc.push_back(Tok.getLocation()); 3805 ConsumeAnyToken(); 3806 // Parse ':' 3807 ConsumeAnyToken(); 3808 } else { 3809 Arg.push_back(OMPC_DEVICE_unknown); 3810 KLoc.emplace_back(); 3811 } 3812 } else { 3813 assert(Kind == OMPC_if); 3814 KLoc.push_back(Tok.getLocation()); 3815 TentativeParsingAction TPA(*this); 3816 auto DK = parseOpenMPDirectiveKind(*this); 3817 Arg.push_back(DK); 3818 if (DK != OMPD_unknown) { 3819 ConsumeToken(); 3820 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 3821 TPA.Commit(); 3822 DelimLoc = ConsumeToken(); 3823 } else { 3824 TPA.Revert(); 3825 Arg.back() = unsigned(OMPD_unknown); 3826 } 3827 } else { 3828 TPA.Revert(); 3829 } 3830 } 3831 3832 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 3833 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 3834 Kind == OMPC_if || Kind == OMPC_device; 3835 if (NeedAnExpression) { 3836 SourceLocation ELoc = Tok.getLocation(); 3837 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 3838 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 3839 Val = 3840 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3841 } 3842 3843 // Parse ')'. 3844 SourceLocation RLoc = Tok.getLocation(); 3845 if (!T.consumeClose()) 3846 RLoc = T.getCloseLocation(); 3847 3848 if (NeedAnExpression && Val.isInvalid()) 3849 return nullptr; 3850 3851 if (ParseOnly) 3852 return nullptr; 3853 return Actions.ActOnOpenMPSingleExprWithArgClause( 3854 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 3855 } 3856 3857 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 3858 UnqualifiedId &ReductionId) { 3859 if (ReductionIdScopeSpec.isEmpty()) { 3860 auto OOK = OO_None; 3861 switch (P.getCurToken().getKind()) { 3862 case tok::plus: 3863 OOK = OO_Plus; 3864 break; 3865 case tok::minus: 3866 OOK = OO_Minus; 3867 break; 3868 case tok::star: 3869 OOK = OO_Star; 3870 break; 3871 case tok::amp: 3872 OOK = OO_Amp; 3873 break; 3874 case tok::pipe: 3875 OOK = OO_Pipe; 3876 break; 3877 case tok::caret: 3878 OOK = OO_Caret; 3879 break; 3880 case tok::ampamp: 3881 OOK = OO_AmpAmp; 3882 break; 3883 case tok::pipepipe: 3884 OOK = OO_PipePipe; 3885 break; 3886 default: 3887 break; 3888 } 3889 if (OOK != OO_None) { 3890 SourceLocation OpLoc = P.ConsumeToken(); 3891 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 3892 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 3893 return false; 3894 } 3895 } 3896 return P.ParseUnqualifiedId( 3897 ReductionIdScopeSpec, /*ObjectType=*/nullptr, 3898 /*ObjectHadErrors=*/false, /*EnteringContext*/ false, 3899 /*AllowDestructorName*/ false, 3900 /*AllowConstructorName*/ false, 3901 /*AllowDeductionGuide*/ false, nullptr, ReductionId); 3902 } 3903 3904 /// Checks if the token is a valid map-type-modifier. 3905 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses. 3906 static OpenMPMapModifierKind isMapModifier(Parser &P) { 3907 Token Tok = P.getCurToken(); 3908 if (!Tok.is(tok::identifier)) 3909 return OMPC_MAP_MODIFIER_unknown; 3910 3911 Preprocessor &PP = P.getPreprocessor(); 3912 OpenMPMapModifierKind TypeModifier = 3913 static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType( 3914 OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); 3915 return TypeModifier; 3916 } 3917 3918 /// Parse the mapper modifier in map, to, and from clauses. 3919 bool Parser::parseMapperModifier(Sema::OpenMPVarListDataTy &Data) { 3920 // Parse '('. 3921 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 3922 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 3923 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3924 StopBeforeMatch); 3925 return true; 3926 } 3927 // Parse mapper-identifier 3928 if (getLangOpts().CPlusPlus) 3929 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3930 /*ObjectType=*/nullptr, 3931 /*ObjectHasErrors=*/false, 3932 /*EnteringContext=*/false); 3933 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 3934 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 3935 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3936 StopBeforeMatch); 3937 return true; 3938 } 3939 auto &DeclNames = Actions.getASTContext().DeclarationNames; 3940 Data.ReductionOrMapperId = DeclarationNameInfo( 3941 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 3942 ConsumeToken(); 3943 // Parse ')'. 3944 return T.consumeClose(); 3945 } 3946 3947 /// Parse map-type-modifiers in map clause. 3948 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3949 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) | 3950 /// present 3951 bool Parser::parseMapTypeModifiers(Sema::OpenMPVarListDataTy &Data) { 3952 while (getCurToken().isNot(tok::colon)) { 3953 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 3954 if (TypeModifier == OMPC_MAP_MODIFIER_always || 3955 TypeModifier == OMPC_MAP_MODIFIER_close || 3956 TypeModifier == OMPC_MAP_MODIFIER_present || 3957 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) { 3958 Data.MapTypeModifiers.push_back(TypeModifier); 3959 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3960 ConsumeToken(); 3961 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 3962 Data.MapTypeModifiers.push_back(TypeModifier); 3963 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3964 ConsumeToken(); 3965 if (parseMapperModifier(Data)) 3966 return true; 3967 } else { 3968 // For the case of unknown map-type-modifier or a map-type. 3969 // Map-type is followed by a colon; the function returns when it 3970 // encounters a token followed by a colon. 3971 if (Tok.is(tok::comma)) { 3972 Diag(Tok, diag::err_omp_map_type_modifier_missing); 3973 ConsumeToken(); 3974 continue; 3975 } 3976 // Potential map-type token as it is followed by a colon. 3977 if (PP.LookAhead(0).is(tok::colon)) 3978 return false; 3979 Diag(Tok, diag::err_omp_unknown_map_type_modifier) 3980 << (getLangOpts().OpenMP >= 51 ? 1 : 0) 3981 << getLangOpts().OpenMPExtensions; 3982 ConsumeToken(); 3983 } 3984 if (getCurToken().is(tok::comma)) 3985 ConsumeToken(); 3986 } 3987 return false; 3988 } 3989 3990 /// Checks if the token is a valid map-type. 3991 /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses. 3992 static OpenMPMapClauseKind isMapType(Parser &P) { 3993 Token Tok = P.getCurToken(); 3994 // The map-type token can be either an identifier or the C++ delete keyword. 3995 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 3996 return OMPC_MAP_unknown; 3997 Preprocessor &PP = P.getPreprocessor(); 3998 OpenMPMapClauseKind MapType = 3999 static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 4000 OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); 4001 return MapType; 4002 } 4003 4004 /// Parse map-type in map clause. 4005 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 4006 /// where, map-type ::= to | from | tofrom | alloc | release | delete 4007 static void parseMapType(Parser &P, Sema::OpenMPVarListDataTy &Data) { 4008 Token Tok = P.getCurToken(); 4009 if (Tok.is(tok::colon)) { 4010 P.Diag(Tok, diag::err_omp_map_type_missing); 4011 return; 4012 } 4013 Data.ExtraModifier = isMapType(P); 4014 if (Data.ExtraModifier == OMPC_MAP_unknown) 4015 P.Diag(Tok, diag::err_omp_unknown_map_type); 4016 P.ConsumeToken(); 4017 } 4018 4019 /// Parses simple expression in parens for single-expression clauses of OpenMP 4020 /// constructs. 4021 ExprResult Parser::ParseOpenMPIteratorsExpr() { 4022 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" && 4023 "Expected 'iterator' token."); 4024 SourceLocation IteratorKwLoc = ConsumeToken(); 4025 4026 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 4027 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator")) 4028 return ExprError(); 4029 4030 SourceLocation LLoc = T.getOpenLocation(); 4031 SmallVector<Sema::OMPIteratorData, 4> Data; 4032 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 4033 // Check if the type parsing is required. 4034 ParsedType IteratorType; 4035 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) { 4036 // identifier '=' is not found - parse type. 4037 TypeResult TR = ParseTypeName(); 4038 if (TR.isInvalid()) { 4039 T.skipToEnd(); 4040 return ExprError(); 4041 } 4042 IteratorType = TR.get(); 4043 } 4044 4045 // Parse identifier. 4046 IdentifierInfo *II = nullptr; 4047 SourceLocation IdLoc; 4048 if (Tok.is(tok::identifier)) { 4049 II = Tok.getIdentifierInfo(); 4050 IdLoc = ConsumeToken(); 4051 } else { 4052 Diag(Tok, diag::err_expected_unqualified_id) << 0; 4053 } 4054 4055 // Parse '='. 4056 SourceLocation AssignLoc; 4057 if (Tok.is(tok::equal)) 4058 AssignLoc = ConsumeToken(); 4059 else 4060 Diag(Tok, diag::err_omp_expected_equal_in_iterator); 4061 4062 // Parse range-specification - <begin> ':' <end> [ ':' <step> ] 4063 ColonProtectionRAIIObject ColonRAII(*this); 4064 // Parse <begin> 4065 SourceLocation Loc = Tok.getLocation(); 4066 ExprResult LHS = ParseCastExpression(AnyCastExpr); 4067 ExprResult Begin = Actions.CorrectDelayedTyposInExpr( 4068 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4069 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc, 4070 /*DiscardedValue=*/false); 4071 // Parse ':'. 4072 SourceLocation ColonLoc; 4073 if (Tok.is(tok::colon)) 4074 ColonLoc = ConsumeToken(); 4075 4076 // Parse <end> 4077 Loc = Tok.getLocation(); 4078 LHS = ParseCastExpression(AnyCastExpr); 4079 ExprResult End = Actions.CorrectDelayedTyposInExpr( 4080 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4081 End = Actions.ActOnFinishFullExpr(End.get(), Loc, 4082 /*DiscardedValue=*/false); 4083 4084 SourceLocation SecColonLoc; 4085 ExprResult Step; 4086 // Parse optional step. 4087 if (Tok.is(tok::colon)) { 4088 // Parse ':' 4089 SecColonLoc = ConsumeToken(); 4090 // Parse <step> 4091 Loc = Tok.getLocation(); 4092 LHS = ParseCastExpression(AnyCastExpr); 4093 Step = Actions.CorrectDelayedTyposInExpr( 4094 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4095 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc, 4096 /*DiscardedValue=*/false); 4097 } 4098 4099 // Parse ',' or ')' 4100 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 4101 Diag(Tok, diag::err_omp_expected_punc_after_iterator); 4102 if (Tok.is(tok::comma)) 4103 ConsumeToken(); 4104 4105 Sema::OMPIteratorData &D = Data.emplace_back(); 4106 D.DeclIdent = II; 4107 D.DeclIdentLoc = IdLoc; 4108 D.Type = IteratorType; 4109 D.AssignLoc = AssignLoc; 4110 D.ColonLoc = ColonLoc; 4111 D.SecColonLoc = SecColonLoc; 4112 D.Range.Begin = Begin.get(); 4113 D.Range.End = End.get(); 4114 D.Range.Step = Step.get(); 4115 } 4116 4117 // Parse ')'. 4118 SourceLocation RLoc = Tok.getLocation(); 4119 if (!T.consumeClose()) 4120 RLoc = T.getCloseLocation(); 4121 4122 return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc, 4123 Data); 4124 } 4125 4126 bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind, 4127 Sema::OpenMPVarListDataTy &Data, 4128 const LangOptions &LangOpts) { 4129 // Currently the only reserved locator is 'omp_all_memory' which is only 4130 // allowed on a depend clause. 4131 if (Kind != OMPC_depend || LangOpts.OpenMP < 51) 4132 return false; 4133 4134 if (Tok.is(tok::identifier) && 4135 Tok.getIdentifierInfo()->isStr("omp_all_memory")) { 4136 4137 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory || 4138 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory) 4139 Diag(Tok, diag::warn_omp_more_one_omp_all_memory); 4140 else if (Data.ExtraModifier != OMPC_DEPEND_out && 4141 Data.ExtraModifier != OMPC_DEPEND_inout) 4142 Diag(Tok, diag::err_omp_requires_out_inout_depend_type); 4143 else 4144 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out 4145 ? OMPC_DEPEND_outallmemory 4146 : OMPC_DEPEND_inoutallmemory; 4147 ConsumeToken(); 4148 return true; 4149 } 4150 return false; 4151 } 4152 4153 /// Parses clauses with list. 4154 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 4155 OpenMPClauseKind Kind, 4156 SmallVectorImpl<Expr *> &Vars, 4157 Sema::OpenMPVarListDataTy &Data) { 4158 UnqualifiedId UnqualifiedReductionId; 4159 bool InvalidReductionId = false; 4160 bool IsInvalidMapperModifier = false; 4161 4162 // Parse '('. 4163 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 4164 if (T.expectAndConsume(diag::err_expected_lparen_after, 4165 getOpenMPClauseName(Kind).data())) 4166 return true; 4167 4168 bool HasIterator = false; 4169 bool NeedRParenForLinear = false; 4170 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 4171 tok::annot_pragma_openmp_end); 4172 // Handle reduction-identifier for reduction clause. 4173 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 4174 Kind == OMPC_in_reduction) { 4175 Data.ExtraModifier = OMPC_REDUCTION_unknown; 4176 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 && 4177 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) && 4178 NextToken().is(tok::comma)) { 4179 // Parse optional reduction modifier. 4180 Data.ExtraModifier = 4181 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4182 Data.ExtraModifierLoc = Tok.getLocation(); 4183 ConsumeToken(); 4184 assert(Tok.is(tok::comma) && "Expected comma."); 4185 (void)ConsumeToken(); 4186 } 4187 ColonProtectionRAIIObject ColonRAII(*this); 4188 if (getLangOpts().CPlusPlus) 4189 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 4190 /*ObjectType=*/nullptr, 4191 /*ObjectHasErrors=*/false, 4192 /*EnteringContext=*/false); 4193 InvalidReductionId = ParseReductionId( 4194 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 4195 if (InvalidReductionId) { 4196 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4197 StopBeforeMatch); 4198 } 4199 if (Tok.is(tok::colon)) 4200 Data.ColonLoc = ConsumeToken(); 4201 else 4202 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 4203 if (!InvalidReductionId) 4204 Data.ReductionOrMapperId = 4205 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 4206 } else if (Kind == OMPC_depend) { 4207 if (getLangOpts().OpenMP >= 50) { 4208 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { 4209 // Handle optional dependence modifier. 4210 // iterator(iterators-definition) 4211 // where iterators-definition is iterator-specifier [, 4212 // iterators-definition ] 4213 // where iterator-specifier is [ iterator-type ] identifier = 4214 // range-specification 4215 HasIterator = true; 4216 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 4217 ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); 4218 Data.DepModOrTailExpr = IteratorRes.get(); 4219 // Parse ',' 4220 ExpectAndConsume(tok::comma); 4221 } 4222 } 4223 // Handle dependency type for depend clause. 4224 ColonProtectionRAIIObject ColonRAII(*this); 4225 Data.ExtraModifier = getOpenMPSimpleClauseType( 4226 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 4227 getLangOpts()); 4228 Data.ExtraModifierLoc = Tok.getLocation(); 4229 if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 4230 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4231 StopBeforeMatch); 4232 } else { 4233 ConsumeToken(); 4234 // Special processing for depend(source) clause. 4235 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 4236 // Parse ')'. 4237 T.consumeClose(); 4238 return false; 4239 } 4240 } 4241 if (Tok.is(tok::colon)) { 4242 Data.ColonLoc = ConsumeToken(); 4243 } else { 4244 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 4245 : diag::warn_pragma_expected_colon) 4246 << "dependency type"; 4247 } 4248 } else if (Kind == OMPC_linear) { 4249 // Try to parse modifier if any. 4250 Data.ExtraModifier = OMPC_LINEAR_val; 4251 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 4252 Data.ExtraModifier = 4253 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4254 Data.ExtraModifierLoc = ConsumeToken(); 4255 LinearT.consumeOpen(); 4256 NeedRParenForLinear = true; 4257 } 4258 } else if (Kind == OMPC_lastprivate) { 4259 // Try to parse modifier if any. 4260 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 4261 // Conditional modifier allowed only in OpenMP 5.0 and not supported in 4262 // distribute and taskloop based directives. 4263 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 4264 !isOpenMPTaskLoopDirective(DKind)) && 4265 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 4266 Data.ExtraModifier = 4267 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4268 Data.ExtraModifierLoc = Tok.getLocation(); 4269 ConsumeToken(); 4270 assert(Tok.is(tok::colon) && "Expected colon."); 4271 Data.ColonLoc = ConsumeToken(); 4272 } 4273 } else if (Kind == OMPC_map) { 4274 // Handle map type for map clause. 4275 ColonProtectionRAIIObject ColonRAII(*this); 4276 4277 // The first identifier may be a list item, a map-type or a 4278 // map-type-modifier. The map-type can also be delete which has the same 4279 // spelling of the C++ delete keyword. 4280 Data.ExtraModifier = OMPC_MAP_unknown; 4281 Data.ExtraModifierLoc = Tok.getLocation(); 4282 4283 // Check for presence of a colon in the map clause. 4284 TentativeParsingAction TPA(*this); 4285 bool ColonPresent = false; 4286 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4287 StopBeforeMatch)) { 4288 if (Tok.is(tok::colon)) 4289 ColonPresent = true; 4290 } 4291 TPA.Revert(); 4292 // Only parse map-type-modifier[s] and map-type if a colon is present in 4293 // the map clause. 4294 if (ColonPresent) { 4295 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 4296 if (!IsInvalidMapperModifier) 4297 parseMapType(*this, Data); 4298 else 4299 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 4300 } 4301 if (Data.ExtraModifier == OMPC_MAP_unknown) { 4302 Data.ExtraModifier = OMPC_MAP_tofrom; 4303 Data.IsMapTypeImplicit = true; 4304 } 4305 4306 if (Tok.is(tok::colon)) 4307 Data.ColonLoc = ConsumeToken(); 4308 } else if (Kind == OMPC_to || Kind == OMPC_from) { 4309 while (Tok.is(tok::identifier)) { 4310 auto Modifier = static_cast<OpenMPMotionModifierKind>( 4311 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts())); 4312 if (Modifier == OMPC_MOTION_MODIFIER_unknown) 4313 break; 4314 Data.MotionModifiers.push_back(Modifier); 4315 Data.MotionModifiersLoc.push_back(Tok.getLocation()); 4316 ConsumeToken(); 4317 if (Modifier == OMPC_MOTION_MODIFIER_mapper) { 4318 IsInvalidMapperModifier = parseMapperModifier(Data); 4319 if (IsInvalidMapperModifier) 4320 break; 4321 } 4322 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers. 4323 if (getLangOpts().OpenMP < 51) 4324 break; 4325 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'. 4326 // TODO: Is that intentional? 4327 if (Tok.is(tok::comma)) 4328 ConsumeToken(); 4329 } 4330 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) { 4331 if (!IsInvalidMapperModifier) { 4332 if (getLangOpts().OpenMP < 51) 4333 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 4334 else 4335 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier"; 4336 } 4337 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4338 StopBeforeMatch); 4339 } 4340 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is 4341 // that intentional? 4342 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) && 4343 Tok.is(tok::colon)) 4344 Data.ColonLoc = ConsumeToken(); 4345 } else if (Kind == OMPC_allocate || 4346 (Kind == OMPC_affinity && Tok.is(tok::identifier) && 4347 PP.getSpelling(Tok) == "iterator")) { 4348 // Handle optional allocator expression followed by colon delimiter. 4349 ColonProtectionRAIIObject ColonRAII(*this); 4350 TentativeParsingAction TPA(*this); 4351 // OpenMP 5.0, 2.10.1, task Construct. 4352 // where aff-modifier is one of the following: 4353 // iterator(iterators-definition) 4354 ExprResult Tail; 4355 if (Kind == OMPC_allocate) { 4356 Tail = ParseAssignmentExpression(); 4357 } else { 4358 HasIterator = true; 4359 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 4360 Tail = ParseOpenMPIteratorsExpr(); 4361 } 4362 Tail = Actions.CorrectDelayedTyposInExpr(Tail); 4363 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 4364 /*DiscardedValue=*/false); 4365 if (Tail.isUsable()) { 4366 if (Tok.is(tok::colon)) { 4367 Data.DepModOrTailExpr = Tail.get(); 4368 Data.ColonLoc = ConsumeToken(); 4369 TPA.Commit(); 4370 } else { 4371 // Colon not found, parse only list of variables. 4372 TPA.Revert(); 4373 } 4374 } else { 4375 // Parsing was unsuccessfull, revert and skip to the end of clause or 4376 // directive. 4377 TPA.Revert(); 4378 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4379 StopBeforeMatch); 4380 } 4381 } else if (Kind == OMPC_adjust_args) { 4382 // Handle adjust-op for adjust_args clause. 4383 ColonProtectionRAIIObject ColonRAII(*this); 4384 Data.ExtraModifier = getOpenMPSimpleClauseType( 4385 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 4386 getLangOpts()); 4387 Data.ExtraModifierLoc = Tok.getLocation(); 4388 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) { 4389 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4390 StopBeforeMatch); 4391 } else { 4392 ConsumeToken(); 4393 if (Tok.is(tok::colon)) 4394 Data.ColonLoc = Tok.getLocation(); 4395 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon, 4396 "adjust-op"); 4397 } 4398 } 4399 4400 bool IsComma = 4401 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 4402 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 4403 (Kind == OMPC_reduction && !InvalidReductionId) || 4404 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 4405 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) || 4406 (Kind == OMPC_adjust_args && 4407 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown); 4408 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 4409 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 4410 Tok.isNot(tok::annot_pragma_openmp_end))) { 4411 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); 4412 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 4413 if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) { 4414 // Parse variable 4415 ExprResult VarExpr = 4416 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 4417 if (VarExpr.isUsable()) { 4418 Vars.push_back(VarExpr.get()); 4419 } else { 4420 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4421 StopBeforeMatch); 4422 } 4423 } 4424 // Skip ',' if any 4425 IsComma = Tok.is(tok::comma); 4426 if (IsComma) 4427 ConsumeToken(); 4428 else if (Tok.isNot(tok::r_paren) && 4429 Tok.isNot(tok::annot_pragma_openmp_end) && 4430 (!MayHaveTail || Tok.isNot(tok::colon))) 4431 Diag(Tok, diag::err_omp_expected_punc) 4432 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 4433 : getOpenMPClauseName(Kind)) 4434 << (Kind == OMPC_flush); 4435 } 4436 4437 // Parse ')' for linear clause with modifier. 4438 if (NeedRParenForLinear) 4439 LinearT.consumeClose(); 4440 4441 // Parse ':' linear-step (or ':' alignment). 4442 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 4443 if (MustHaveTail) { 4444 Data.ColonLoc = Tok.getLocation(); 4445 SourceLocation ELoc = ConsumeToken(); 4446 ExprResult Tail = ParseAssignmentExpression(); 4447 Tail = 4448 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 4449 if (Tail.isUsable()) 4450 Data.DepModOrTailExpr = Tail.get(); 4451 else 4452 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4453 StopBeforeMatch); 4454 } 4455 4456 // Parse ')'. 4457 Data.RLoc = Tok.getLocation(); 4458 if (!T.consumeClose()) 4459 Data.RLoc = T.getCloseLocation(); 4460 // Exit from scope when the iterator is used in depend clause. 4461 if (HasIterator) 4462 ExitScope(); 4463 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 4464 (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || 4465 IsInvalidMapperModifier; 4466 } 4467 4468 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 4469 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction', 4470 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'. 4471 /// 4472 /// private-clause: 4473 /// 'private' '(' list ')' 4474 /// firstprivate-clause: 4475 /// 'firstprivate' '(' list ')' 4476 /// lastprivate-clause: 4477 /// 'lastprivate' '(' list ')' 4478 /// shared-clause: 4479 /// 'shared' '(' list ')' 4480 /// linear-clause: 4481 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 4482 /// aligned-clause: 4483 /// 'aligned' '(' list [ ':' alignment ] ')' 4484 /// reduction-clause: 4485 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')' 4486 /// task_reduction-clause: 4487 /// 'task_reduction' '(' reduction-identifier ':' list ')' 4488 /// in_reduction-clause: 4489 /// 'in_reduction' '(' reduction-identifier ':' list ')' 4490 /// copyprivate-clause: 4491 /// 'copyprivate' '(' list ')' 4492 /// flush-clause: 4493 /// 'flush' '(' list ')' 4494 /// depend-clause: 4495 /// 'depend' '(' in | out | inout : list | source ')' 4496 /// map-clause: 4497 /// 'map' '(' [ [ always [,] ] [ close [,] ] 4498 /// [ mapper '(' mapper-identifier ')' [,] ] 4499 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 4500 /// to-clause: 4501 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 4502 /// from-clause: 4503 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 4504 /// use_device_ptr-clause: 4505 /// 'use_device_ptr' '(' list ')' 4506 /// use_device_addr-clause: 4507 /// 'use_device_addr' '(' list ')' 4508 /// is_device_ptr-clause: 4509 /// 'is_device_ptr' '(' list ')' 4510 /// has_device_addr-clause: 4511 /// 'has_device_addr' '(' list ')' 4512 /// allocate-clause: 4513 /// 'allocate' '(' [ allocator ':' ] list ')' 4514 /// nontemporal-clause: 4515 /// 'nontemporal' '(' list ')' 4516 /// inclusive-clause: 4517 /// 'inclusive' '(' list ')' 4518 /// exclusive-clause: 4519 /// 'exclusive' '(' list ')' 4520 /// 4521 /// For 'linear' clause linear-list may have the following forms: 4522 /// list 4523 /// modifier(list) 4524 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 4525 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 4526 OpenMPClauseKind Kind, 4527 bool ParseOnly) { 4528 SourceLocation Loc = Tok.getLocation(); 4529 SourceLocation LOpen = ConsumeToken(); 4530 SmallVector<Expr *, 4> Vars; 4531 Sema::OpenMPVarListDataTy Data; 4532 4533 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 4534 return nullptr; 4535 4536 if (ParseOnly) 4537 return nullptr; 4538 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 4539 return Actions.ActOnOpenMPVarListClause(Kind, Vars, Locs, Data); 4540 } 4541