1 //===--- ParseOpenACC.cpp - OpenACC-specific parsing support --------------===// 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 // 9 // This file implements the parsing logic for OpenACC language features. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Basic/OpenACCKinds.h" 14 #include "clang/Parse/ParseDiagnostic.h" 15 #include "clang/Parse/Parser.h" 16 #include "clang/Parse/RAIIObjectsForParser.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/StringSwitch.h" 19 20 using namespace clang; 21 using namespace llvm; 22 23 namespace { 24 // An enum that contains the extended 'partial' parsed variants. This type 25 // should never escape the initial parse functionality, but is useful for 26 // simplifying the implementation. 27 enum class OpenACCDirectiveKindEx { 28 Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid), 29 // 'enter data' and 'exit data' 30 Enter, 31 Exit, 32 }; 33 34 // Translate single-token string representations to the OpenACC Directive Kind. 35 // This doesn't completely comprehend 'Compound Constructs' (as it just 36 // identifies the first token), and doesn't fully handle 'enter data', 'exit 37 // data', nor any of the 'atomic' variants, just the first token of each. So 38 // this should only be used by `ParseOpenACCDirectiveKind`. 39 OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { 40 if (!Tok.is(tok::identifier)) 41 return OpenACCDirectiveKindEx::Invalid; 42 OpenACCDirectiveKind DirKind = 43 llvm::StringSwitch<OpenACCDirectiveKind>( 44 Tok.getIdentifierInfo()->getName()) 45 .Case("parallel", OpenACCDirectiveKind::Parallel) 46 .Case("serial", OpenACCDirectiveKind::Serial) 47 .Case("kernels", OpenACCDirectiveKind::Kernels) 48 .Case("data", OpenACCDirectiveKind::Data) 49 .Case("host_data", OpenACCDirectiveKind::HostData) 50 .Case("loop", OpenACCDirectiveKind::Loop) 51 .Case("cache", OpenACCDirectiveKind::Cache) 52 .Case("atomic", OpenACCDirectiveKind::Atomic) 53 .Case("routine", OpenACCDirectiveKind::Routine) 54 .Case("declare", OpenACCDirectiveKind::Declare) 55 .Case("init", OpenACCDirectiveKind::Init) 56 .Case("shutdown", OpenACCDirectiveKind::Shutdown) 57 .Case("set", OpenACCDirectiveKind::Shutdown) 58 .Case("update", OpenACCDirectiveKind::Update) 59 .Case("wait", OpenACCDirectiveKind::Wait) 60 .Default(OpenACCDirectiveKind::Invalid); 61 62 if (DirKind != OpenACCDirectiveKind::Invalid) 63 return static_cast<OpenACCDirectiveKindEx>(DirKind); 64 65 return llvm::StringSwitch<OpenACCDirectiveKindEx>( 66 Tok.getIdentifierInfo()->getName()) 67 .Case("enter", OpenACCDirectiveKindEx::Enter) 68 .Case("exit", OpenACCDirectiveKindEx::Exit) 69 .Default(OpenACCDirectiveKindEx::Invalid); 70 } 71 72 // Translate single-token string representations to the OpenCC Clause Kind. 73 OpenACCClauseKind getOpenACCClauseKind(Token Tok) { 74 // auto is a keyword in some language modes, so make sure we parse it 75 // correctly. 76 if (Tok.is(tok::kw_auto)) 77 return OpenACCClauseKind::Auto; 78 79 // default is a keyword, so make sure we parse it correctly. 80 if (Tok.is(tok::kw_default)) 81 return OpenACCClauseKind::Default; 82 83 // if is also a keyword, make sure we parse it correctly. 84 if (Tok.is(tok::kw_if)) 85 return OpenACCClauseKind::If; 86 87 if (!Tok.is(tok::identifier)) 88 return OpenACCClauseKind::Invalid; 89 90 return llvm::StringSwitch<OpenACCClauseKind>( 91 Tok.getIdentifierInfo()->getName()) 92 .Case("auto", OpenACCClauseKind::Auto) 93 .Case("default", OpenACCClauseKind::Default) 94 .Case("finalize", OpenACCClauseKind::Finalize) 95 .Case("if", OpenACCClauseKind::If) 96 .Case("if_present", OpenACCClauseKind::IfPresent) 97 .Case("independent", OpenACCClauseKind::Independent) 98 .Case("nohost", OpenACCClauseKind::NoHost) 99 .Case("self", OpenACCClauseKind::Self) 100 .Case("seq", OpenACCClauseKind::Seq) 101 .Case("vector", OpenACCClauseKind::Vector) 102 .Case("worker", OpenACCClauseKind::Worker) 103 .Default(OpenACCClauseKind::Invalid); 104 } 105 106 // Since 'atomic' is effectively a compound directive, this will decode the 107 // second part of the directive. 108 OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { 109 if (!Tok.is(tok::identifier)) 110 return OpenACCAtomicKind::Invalid; 111 return llvm::StringSwitch<OpenACCAtomicKind>( 112 Tok.getIdentifierInfo()->getName()) 113 .Case("read", OpenACCAtomicKind::Read) 114 .Case("write", OpenACCAtomicKind::Write) 115 .Case("update", OpenACCAtomicKind::Update) 116 .Case("capture", OpenACCAtomicKind::Capture) 117 .Default(OpenACCAtomicKind::Invalid); 118 } 119 120 OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) { 121 if (!Tok.is(tok::identifier)) 122 return OpenACCDefaultClauseKind::Invalid; 123 124 return llvm::StringSwitch<OpenACCDefaultClauseKind>( 125 Tok.getIdentifierInfo()->getName()) 126 .Case("none", OpenACCDefaultClauseKind::None) 127 .Case("present", OpenACCDefaultClauseKind::Present) 128 .Default(OpenACCDefaultClauseKind::Invalid); 129 } 130 131 enum class OpenACCSpecialTokenKind { 132 ReadOnly, 133 DevNum, 134 Queues, 135 }; 136 137 bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { 138 if (!Tok.is(tok::identifier)) 139 return false; 140 141 switch (Kind) { 142 case OpenACCSpecialTokenKind::ReadOnly: 143 return Tok.getIdentifierInfo()->isStr("readonly"); 144 case OpenACCSpecialTokenKind::DevNum: 145 return Tok.getIdentifierInfo()->isStr("devnum"); 146 case OpenACCSpecialTokenKind::Queues: 147 return Tok.getIdentifierInfo()->isStr("queues"); 148 } 149 llvm_unreachable("Unknown 'Kind' Passed"); 150 } 151 152 bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { 153 if (!Tok.is(tok::identifier)) 154 return false; 155 156 switch (Kind) { 157 case OpenACCDirectiveKind::Parallel: 158 return Tok.getIdentifierInfo()->isStr("parallel"); 159 case OpenACCDirectiveKind::Serial: 160 return Tok.getIdentifierInfo()->isStr("serial"); 161 case OpenACCDirectiveKind::Kernels: 162 return Tok.getIdentifierInfo()->isStr("kernels"); 163 case OpenACCDirectiveKind::Data: 164 return Tok.getIdentifierInfo()->isStr("data"); 165 case OpenACCDirectiveKind::HostData: 166 return Tok.getIdentifierInfo()->isStr("host_data"); 167 case OpenACCDirectiveKind::Loop: 168 return Tok.getIdentifierInfo()->isStr("loop"); 169 case OpenACCDirectiveKind::Cache: 170 return Tok.getIdentifierInfo()->isStr("cache"); 171 172 case OpenACCDirectiveKind::ParallelLoop: 173 case OpenACCDirectiveKind::SerialLoop: 174 case OpenACCDirectiveKind::KernelsLoop: 175 case OpenACCDirectiveKind::EnterData: 176 case OpenACCDirectiveKind::ExitData: 177 return false; 178 179 case OpenACCDirectiveKind::Atomic: 180 return Tok.getIdentifierInfo()->isStr("atomic"); 181 case OpenACCDirectiveKind::Routine: 182 return Tok.getIdentifierInfo()->isStr("routine"); 183 case OpenACCDirectiveKind::Declare: 184 return Tok.getIdentifierInfo()->isStr("declare"); 185 case OpenACCDirectiveKind::Init: 186 return Tok.getIdentifierInfo()->isStr("init"); 187 case OpenACCDirectiveKind::Shutdown: 188 return Tok.getIdentifierInfo()->isStr("shutdown"); 189 case OpenACCDirectiveKind::Set: 190 return Tok.getIdentifierInfo()->isStr("set"); 191 case OpenACCDirectiveKind::Update: 192 return Tok.getIdentifierInfo()->isStr("update"); 193 case OpenACCDirectiveKind::Wait: 194 return Tok.getIdentifierInfo()->isStr("wait"); 195 case OpenACCDirectiveKind::Invalid: 196 return false; 197 } 198 llvm_unreachable("Unknown 'Kind' Passed"); 199 } 200 201 /// Used for cases where we expect an identifier-like token, but don't want to 202 /// give awkward error messages in cases where it is accidentially a keyword. 203 bool expectIdentifierOrKeyword(Parser &P) { 204 Token Tok = P.getCurToken(); 205 206 if (Tok.is(tok::identifier)) 207 return false; 208 209 if (!Tok.isAnnotation() && Tok.getIdentifierInfo() && 210 Tok.getIdentifierInfo()->isKeyword(P.getLangOpts())) 211 return false; 212 213 P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; 214 return true; 215 } 216 217 OpenACCDirectiveKind 218 ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, 219 OpenACCDirectiveKindEx ExtDirKind) { 220 Token SecondTok = P.getCurToken(); 221 222 if (SecondTok.isAnnotation()) { 223 P.Diag(FirstTok, diag::err_acc_invalid_directive) 224 << 0 << FirstTok.getIdentifierInfo(); 225 return OpenACCDirectiveKind::Invalid; 226 } 227 228 // Consume the second name anyway, this way we can continue on without making 229 // this oddly look like a clause. 230 P.ConsumeAnyToken(); 231 232 if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { 233 if (!SecondTok.is(tok::identifier)) 234 P.Diag(SecondTok, diag::err_expected) << tok::identifier; 235 else 236 P.Diag(FirstTok, diag::err_acc_invalid_directive) 237 << 1 << FirstTok.getIdentifierInfo()->getName() 238 << SecondTok.getIdentifierInfo()->getName(); 239 return OpenACCDirectiveKind::Invalid; 240 } 241 242 return ExtDirKind == OpenACCDirectiveKindEx::Enter 243 ? OpenACCDirectiveKind::EnterData 244 : OpenACCDirectiveKind::ExitData; 245 } 246 247 OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) { 248 Token AtomicClauseToken = P.getCurToken(); 249 250 // #pragma acc atomic is equivilent to update: 251 if (AtomicClauseToken.isAnnotation()) 252 return OpenACCAtomicKind::Update; 253 254 OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken); 255 256 // If we don't know what this is, treat it as 'nothing', and treat the rest of 257 // this as a clause list, which, despite being invalid, is likely what the 258 // user was trying to do. 259 if (AtomicKind == OpenACCAtomicKind::Invalid) 260 return OpenACCAtomicKind::Update; 261 262 P.ConsumeToken(); 263 return AtomicKind; 264 } 265 266 // Parse and consume the tokens for OpenACC Directive/Construct kinds. 267 OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { 268 Token FirstTok = P.getCurToken(); 269 270 // Just #pragma acc can get us immediately to the end, make sure we don't 271 // introspect on the spelling before then. 272 if (FirstTok.isNot(tok::identifier)) { 273 P.Diag(FirstTok, diag::err_acc_missing_directive); 274 275 if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 276 P.ConsumeAnyToken(); 277 278 return OpenACCDirectiveKind::Invalid; 279 } 280 281 P.ConsumeToken(); 282 283 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok); 284 285 // OpenACCDirectiveKindEx is meant to be an extended list 286 // over OpenACCDirectiveKind, so any value below Invalid is one of the 287 // OpenACCDirectiveKind values. This switch takes care of all of the extra 288 // parsing required for the Extended values. At the end of this block, 289 // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can 290 // immediately cast it and use it as that. 291 if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) { 292 switch (ExDirKind) { 293 case OpenACCDirectiveKindEx::Invalid: { 294 P.Diag(FirstTok, diag::err_acc_invalid_directive) 295 << 0 << FirstTok.getIdentifierInfo(); 296 return OpenACCDirectiveKind::Invalid; 297 } 298 case OpenACCDirectiveKindEx::Enter: 299 case OpenACCDirectiveKindEx::Exit: 300 return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind); 301 } 302 } 303 304 OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind); 305 306 // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any 307 // other attempt at a combined construct will be diagnosed as an invalid 308 // clause. 309 Token SecondTok = P.getCurToken(); 310 if (!SecondTok.isAnnotation() && 311 isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) { 312 switch (DirKind) { 313 default: 314 // Nothing to do except in the below cases, as they should be diagnosed as 315 // a clause. 316 break; 317 case OpenACCDirectiveKind::Parallel: 318 P.ConsumeToken(); 319 return OpenACCDirectiveKind::ParallelLoop; 320 case OpenACCDirectiveKind::Serial: 321 P.ConsumeToken(); 322 return OpenACCDirectiveKind::SerialLoop; 323 case OpenACCDirectiveKind::Kernels: 324 P.ConsumeToken(); 325 return OpenACCDirectiveKind::KernelsLoop; 326 } 327 } 328 329 return DirKind; 330 } 331 332 bool ClauseHasOptionalParens(OpenACCClauseKind Kind) { 333 return Kind == OpenACCClauseKind::Self; 334 } 335 336 bool ClauseHasRequiredParens(OpenACCClauseKind Kind) { 337 return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If; 338 } 339 340 ExprResult ParseOpenACCConditionalExpr(Parser &P) { 341 // FIXME: It isn't clear if the spec saying 'condition' means the same as 342 // it does in an if/while/etc (See ParseCXXCondition), however as it was 343 // written with Fortran/C in mind, we're going to assume it just means an 344 // 'expression evaluating to boolean'. 345 return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression()); 346 } 347 348 bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) { 349 BalancedDelimiterTracker Parens(P, tok::l_paren, 350 tok::annot_pragma_openacc_end); 351 352 if (ClauseHasRequiredParens(Kind)) { 353 if (Parens.expectAndConsume()) { 354 // We are missing a paren, so assume that the person just forgot the 355 // parameter. Return 'false' so we try to continue on and parse the next 356 // clause. 357 P.SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, 358 Parser::StopBeforeMatch); 359 return false; 360 } 361 362 switch (Kind) { 363 case OpenACCClauseKind::Default: { 364 Token DefKindTok = P.getCurToken(); 365 366 if (expectIdentifierOrKeyword(P)) 367 break; 368 369 P.ConsumeToken(); 370 371 if (getOpenACCDefaultClauseKind(DefKindTok) == 372 OpenACCDefaultClauseKind::Invalid) 373 P.Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); 374 375 break; 376 } 377 case OpenACCClauseKind::If: { 378 ExprResult CondExpr = ParseOpenACCConditionalExpr(P); 379 // An invalid expression can be just about anything, so just give up on 380 // this clause list. 381 if (CondExpr.isInvalid()) 382 return true; 383 break; 384 } 385 default: 386 llvm_unreachable("Not a required parens type?"); 387 } 388 389 return Parens.consumeClose(); 390 } else if (ClauseHasOptionalParens(Kind)) { 391 if (!Parens.consumeOpen()) { 392 switch (Kind) { 393 case OpenACCClauseKind::Self: { 394 ExprResult CondExpr = ParseOpenACCConditionalExpr(P); 395 // An invalid expression can be just about anything, so just give up on 396 // this clause list. 397 if (CondExpr.isInvalid()) 398 return true; 399 break; 400 } 401 default: 402 llvm_unreachable("Not an optional parens type?"); 403 } 404 Parens.consumeClose(); 405 } 406 } 407 return false; 408 } 409 410 // The OpenACC Clause List is a comma or space-delimited list of clauses (see 411 // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't 412 // really have its owner grammar and each individual one has its own definition. 413 // However, they all are named with a single-identifier (or auto/default!) 414 // token, followed in some cases by either braces or parens. 415 bool ParseOpenACCClause(Parser &P) { 416 // A number of clause names are actually keywords, so accept a keyword that 417 // can be converted to a name. 418 if (expectIdentifierOrKeyword(P)) 419 return true; 420 421 OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken()); 422 423 if (Kind == OpenACCClauseKind::Invalid) 424 return P.Diag(P.getCurToken(), diag::err_acc_invalid_clause) 425 << P.getCurToken().getIdentifierInfo(); 426 427 // Consume the clause name. 428 P.ConsumeToken(); 429 430 return ParseOpenACCClauseParams(P, Kind); 431 } 432 433 // Skip until we see the end of pragma token, but don't consume it. This is us 434 // just giving up on the rest of the pragma so we can continue executing. We 435 // have to do this because 'SkipUntil' considers paren balancing, which isn't 436 // what we want. 437 void SkipUntilEndOfDirective(Parser &P) { 438 while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 439 P.ConsumeAnyToken(); 440 } 441 442 // OpenACC 3.3, section 1.7: 443 // To simplify the specification and convey appropriate constraint information, 444 // a pqr-list is a comma-separated list of pdr items. The one exception is a 445 // clause-list, which is a list of one or more clauses optionally separated by 446 // commas. 447 void ParseOpenACCClauseList(Parser &P) { 448 bool FirstClause = true; 449 while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) { 450 // Comma is optional in a clause-list. 451 if (!FirstClause && P.getCurToken().is(tok::comma)) 452 P.ConsumeToken(); 453 FirstClause = false; 454 455 // Recovering from a bad clause is really difficult, so we just give up on 456 // error. 457 if (ParseOpenACCClause(P)) { 458 SkipUntilEndOfDirective(P); 459 return; 460 } 461 } 462 } 463 464 } // namespace 465 466 /// OpenACC 3.3, section 2.16: 467 /// In this section and throughout the specification, the term wait-argument 468 /// means: 469 /// [ devnum : int-expr : ] [ queues : ] async-argument-list 470 bool Parser::ParseOpenACCWaitArgument() { 471 // [devnum : int-expr : ] 472 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && 473 NextToken().is(tok::colon)) { 474 // Consume devnum. 475 ConsumeToken(); 476 // Consume colon. 477 ConsumeToken(); 478 479 ExprResult IntExpr = 480 getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 481 if (IntExpr.isInvalid()) 482 return true; 483 484 if (ExpectAndConsume(tok::colon)) 485 return true; 486 } 487 488 // [ queues : ] 489 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && 490 NextToken().is(tok::colon)) { 491 // Consume queues. 492 ConsumeToken(); 493 // Consume colon. 494 ConsumeToken(); 495 } 496 497 // OpenACC 3.3, section 2.16: 498 // the term 'async-argument' means a nonnegative scalar integer expression, or 499 // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined 500 // in the C header file and the Fortran opacc module. 501 // 502 // We are parsing this simply as list of assignment expressions (to avoid 503 // comma being troublesome), and will ensure it is an integral type. The 504 // 'special' types are defined as macros, so we can't really check those 505 // (other than perhaps as values at one point?), but the standard does say it 506 // is implementation-defined to use any other negative value. 507 // 508 // 509 bool FirstArg = true; 510 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 511 if (!FirstArg) { 512 if (ExpectAndConsume(tok::comma)) 513 return true; 514 } 515 FirstArg = false; 516 517 ExprResult CurArg = 518 getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 519 520 if (CurArg.isInvalid()) 521 return true; 522 } 523 524 return false; 525 } 526 527 ExprResult Parser::ParseOpenACCIDExpression() { 528 ExprResult Res; 529 if (getLangOpts().CPlusPlus) { 530 Res = ParseCXXIdExpression(/*isAddressOfOperand=*/false); 531 } else { 532 // There isn't anything quite the same as ParseCXXIdExpression for C, so we 533 // need to get the identifier, then call into Sema ourselves. 534 535 if (Tok.isNot(tok::identifier)) { 536 Diag(Tok, diag::err_expected) << tok::identifier; 537 return ExprError(); 538 } 539 540 Token FuncName = getCurToken(); 541 UnqualifiedId Name; 542 CXXScopeSpec ScopeSpec; 543 SourceLocation TemplateKWLoc; 544 Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken()); 545 546 // Ensure this is a valid identifier. We don't accept causing implicit 547 // function declarations per the spec, so always claim to not have trailing 548 // L Paren. 549 Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, 550 Name, /*HasTrailingLParen=*/false, 551 /*isAddressOfOperand=*/false); 552 } 553 554 return getActions().CorrectDelayedTyposInExpr(Res); 555 } 556 557 /// OpenACC 3.3, section 2.10: 558 /// A 'var' in a cache directive must be a single array element or a simple 559 /// subarray. In C and C++, a simple subarray is an array name followed by an 560 /// extended array range specification in brackets, with a start and length such 561 /// as: 562 /// 563 /// arr[lower:length] 564 /// 565 bool Parser::ParseOpenACCCacheVar() { 566 ExprResult ArrayName = ParseOpenACCIDExpression(); 567 if (ArrayName.isInvalid()) 568 return true; 569 570 // If the expression is invalid, just continue parsing the brackets, there 571 // is likely other useful diagnostics we can emit inside of those. 572 573 BalancedDelimiterTracker SquareBrackets(*this, tok::l_square, 574 tok::annot_pragma_openacc_end); 575 576 // Square brackets are required, so error here, and try to recover by moving 577 // until the next comma, or the close paren/end of pragma. 578 if (SquareBrackets.expectAndConsume()) { 579 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, 580 Parser::StopBeforeMatch); 581 return true; 582 } 583 584 ExprResult Lower = getActions().CorrectDelayedTyposInExpr(ParseExpression()); 585 if (Lower.isInvalid()) 586 return true; 587 588 // The 'length' expression is optional, as this could be a single array 589 // element. If there is no colon, we can treat it as that. 590 if (getCurToken().is(tok::colon)) { 591 ConsumeToken(); 592 ExprResult Length = 593 getActions().CorrectDelayedTyposInExpr(ParseExpression()); 594 if (Length.isInvalid()) 595 return true; 596 } 597 598 // Diagnose the square bracket being in the wrong place and continue. 599 return SquareBrackets.consumeClose(); 600 } 601 602 /// OpenACC 3.3, section 2.10: 603 /// In C and C++, the syntax of the cache directive is: 604 /// 605 /// #pragma acc cache ([readonly:]var-list) new-line 606 void Parser::ParseOpenACCCacheVarList() { 607 // If this is the end of the line, just return 'false' and count on the close 608 // paren diagnostic to catch the issue. 609 if (getCurToken().isAnnotation()) 610 return; 611 612 // The VarList is an optional `readonly:` followed by a list of a variable 613 // specifications. First, see if we have `readonly:`, else we back-out and 614 // treat it like the beginning of a reference to a potentially-existing 615 // `readonly` variable. 616 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::ReadOnly, Tok) && 617 NextToken().is(tok::colon)) { 618 // Consume both tokens. 619 ConsumeToken(); 620 ConsumeToken(); 621 // FIXME: Record that this is a 'readonly' so that we can use that during 622 // Sema/AST generation. 623 } 624 625 bool FirstArray = true; 626 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 627 if (!FirstArray) 628 ExpectAndConsume(tok::comma); 629 FirstArray = false; 630 if (ParseOpenACCCacheVar()) 631 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma, 632 StopBeforeMatch); 633 } 634 } 635 636 void Parser::ParseOpenACCDirective() { 637 OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); 638 639 // Once we've parsed the construct/directive name, some have additional 640 // specifiers that need to be taken care of. Atomic has an 'atomic-clause' 641 // that needs to be parsed. 642 if (DirKind == OpenACCDirectiveKind::Atomic) 643 ParseOpenACCAtomicKind(*this); 644 645 // We've successfully parsed the construct/directive name, however a few of 646 // the constructs have optional parens that contain further details. 647 BalancedDelimiterTracker T(*this, tok::l_paren, 648 tok::annot_pragma_openacc_end); 649 650 if (!T.consumeOpen()) { 651 switch (DirKind) { 652 default: 653 Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren); 654 T.skipToEnd(); 655 break; 656 case OpenACCDirectiveKind::Routine: { 657 // Routine has an optional paren-wrapped name of a function in the local 658 // scope. We parse the name, emitting any diagnostics 659 ExprResult RoutineName = ParseOpenACCIDExpression(); 660 // If the routine name is invalid, just skip until the closing paren to 661 // recover more gracefully. 662 if (RoutineName.isInvalid()) 663 T.skipToEnd(); 664 else 665 T.consumeClose(); 666 break; 667 } 668 case OpenACCDirectiveKind::Cache: 669 ParseOpenACCCacheVarList(); 670 // The ParseOpenACCCacheVarList function manages to recover from failures, 671 // so we can always consume the close. 672 T.consumeClose(); 673 break; 674 case OpenACCDirectiveKind::Wait: 675 // OpenACC has an optional paren-wrapped 'wait-argument'. 676 if (ParseOpenACCWaitArgument()) 677 T.skipToEnd(); 678 else 679 T.consumeClose(); 680 break; 681 } 682 } else if (DirKind == OpenACCDirectiveKind::Cache) { 683 // Cache's paren var-list is required, so error here if it isn't provided. 684 // We know that the consumeOpen above left the first non-paren here, so 685 // diagnose, then continue as if it was completely omitted. 686 Diag(Tok, diag::err_expected) << tok::l_paren; 687 } 688 689 // Parses the list of clauses, if present. 690 ParseOpenACCClauseList(*this); 691 692 Diag(getCurToken(), diag::warn_pragma_acc_unimplemented); 693 assert(Tok.is(tok::annot_pragma_openacc_end) && 694 "Didn't parse all OpenACC Clauses"); 695 ConsumeAnnotationToken(); 696 } 697 698 // Parse OpenACC directive on a declaration. 699 Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { 700 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 701 702 ParsingOpenACCDirectiveRAII DirScope(*this); 703 ConsumeAnnotationToken(); 704 705 ParseOpenACCDirective(); 706 707 return nullptr; 708 } 709 710 // Parse OpenACC Directive on a Statement. 711 StmtResult Parser::ParseOpenACCDirectiveStmt() { 712 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 713 714 ParsingOpenACCDirectiveRAII DirScope(*this); 715 ConsumeAnnotationToken(); 716 717 ParseOpenACCDirective(); 718 719 return StmtEmpty(); 720 } 721