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/AST/OpenACCClause.h" 14 #include "clang/Basic/DiagnosticParse.h" 15 #include "clang/Basic/OpenACCKinds.h" 16 #include "clang/Parse/Parser.h" 17 #include "clang/Parse/RAIIObjectsForParser.h" 18 #include "clang/Sema/SemaOpenACC.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/ADT/StringSwitch.h" 21 22 using namespace clang; 23 using namespace llvm; 24 25 namespace { 26 // An enum that contains the extended 'partial' parsed variants. This type 27 // should never escape the initial parse functionality, but is useful for 28 // simplifying the implementation. 29 enum class OpenACCDirectiveKindEx { 30 Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid), 31 // 'enter data' and 'exit data' 32 Enter, 33 Exit, 34 }; 35 36 // Translate single-token string representations to the OpenACC Directive Kind. 37 // This doesn't completely comprehend 'Compound Constructs' (as it just 38 // identifies the first token), and doesn't fully handle 'enter data', 'exit 39 // data', nor any of the 'atomic' variants, just the first token of each. So 40 // this should only be used by `ParseOpenACCDirectiveKind`. 41 OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { 42 if (!Tok.is(tok::identifier)) 43 return OpenACCDirectiveKindEx::Invalid; 44 OpenACCDirectiveKind DirKind = 45 llvm::StringSwitch<OpenACCDirectiveKind>( 46 Tok.getIdentifierInfo()->getName()) 47 .Case("parallel", OpenACCDirectiveKind::Parallel) 48 .Case("serial", OpenACCDirectiveKind::Serial) 49 .Case("kernels", OpenACCDirectiveKind::Kernels) 50 .Case("data", OpenACCDirectiveKind::Data) 51 .Case("host_data", OpenACCDirectiveKind::HostData) 52 .Case("loop", OpenACCDirectiveKind::Loop) 53 .Case("cache", OpenACCDirectiveKind::Cache) 54 .Case("atomic", OpenACCDirectiveKind::Atomic) 55 .Case("routine", OpenACCDirectiveKind::Routine) 56 .Case("declare", OpenACCDirectiveKind::Declare) 57 .Case("init", OpenACCDirectiveKind::Init) 58 .Case("shutdown", OpenACCDirectiveKind::Shutdown) 59 .Case("set", OpenACCDirectiveKind::Set) 60 .Case("update", OpenACCDirectiveKind::Update) 61 .Case("wait", OpenACCDirectiveKind::Wait) 62 .Default(OpenACCDirectiveKind::Invalid); 63 64 if (DirKind != OpenACCDirectiveKind::Invalid) 65 return static_cast<OpenACCDirectiveKindEx>(DirKind); 66 67 return llvm::StringSwitch<OpenACCDirectiveKindEx>( 68 Tok.getIdentifierInfo()->getName()) 69 .Case("enter", OpenACCDirectiveKindEx::Enter) 70 .Case("exit", OpenACCDirectiveKindEx::Exit) 71 .Default(OpenACCDirectiveKindEx::Invalid); 72 } 73 74 // Translate single-token string representations to the OpenCC Clause Kind. 75 OpenACCClauseKind getOpenACCClauseKind(Token Tok) { 76 // auto is a keyword in some language modes, so make sure we parse it 77 // correctly. 78 if (Tok.is(tok::kw_auto)) 79 return OpenACCClauseKind::Auto; 80 81 // default is a keyword, so make sure we parse it correctly. 82 if (Tok.is(tok::kw_default)) 83 return OpenACCClauseKind::Default; 84 85 // if is also a keyword, make sure we parse it correctly. 86 if (Tok.is(tok::kw_if)) 87 return OpenACCClauseKind::If; 88 89 // 'private' is also a keyword, make sure we parse it correctly. 90 if (Tok.is(tok::kw_private)) 91 return OpenACCClauseKind::Private; 92 93 // 'delete' is a keyword, make sure we parse it correctly. 94 if (Tok.is(tok::kw_delete)) 95 return OpenACCClauseKind::Delete; 96 97 if (!Tok.is(tok::identifier)) 98 return OpenACCClauseKind::Invalid; 99 100 return llvm::StringSwitch<OpenACCClauseKind>( 101 Tok.getIdentifierInfo()->getName()) 102 .Case("async", OpenACCClauseKind::Async) 103 .Case("attach", OpenACCClauseKind::Attach) 104 .Case("auto", OpenACCClauseKind::Auto) 105 .Case("bind", OpenACCClauseKind::Bind) 106 .Case("create", OpenACCClauseKind::Create) 107 .Case("pcreate", OpenACCClauseKind::PCreate) 108 .Case("present_or_create", OpenACCClauseKind::PresentOrCreate) 109 .Case("collapse", OpenACCClauseKind::Collapse) 110 .Case("copy", OpenACCClauseKind::Copy) 111 .Case("pcopy", OpenACCClauseKind::PCopy) 112 .Case("present_or_copy", OpenACCClauseKind::PresentOrCopy) 113 .Case("copyin", OpenACCClauseKind::CopyIn) 114 .Case("pcopyin", OpenACCClauseKind::PCopyIn) 115 .Case("present_or_copyin", OpenACCClauseKind::PresentOrCopyIn) 116 .Case("copyout", OpenACCClauseKind::CopyOut) 117 .Case("pcopyout", OpenACCClauseKind::PCopyOut) 118 .Case("present_or_copyout", OpenACCClauseKind::PresentOrCopyOut) 119 .Case("default", OpenACCClauseKind::Default) 120 .Case("default_async", OpenACCClauseKind::DefaultAsync) 121 .Case("delete", OpenACCClauseKind::Delete) 122 .Case("detach", OpenACCClauseKind::Detach) 123 .Case("device", OpenACCClauseKind::Device) 124 .Case("device_num", OpenACCClauseKind::DeviceNum) 125 .Case("device_resident", OpenACCClauseKind::DeviceResident) 126 .Case("device_type", OpenACCClauseKind::DeviceType) 127 .Case("deviceptr", OpenACCClauseKind::DevicePtr) 128 .Case("dtype", OpenACCClauseKind::DType) 129 .Case("finalize", OpenACCClauseKind::Finalize) 130 .Case("firstprivate", OpenACCClauseKind::FirstPrivate) 131 .Case("gang", OpenACCClauseKind::Gang) 132 .Case("host", OpenACCClauseKind::Host) 133 .Case("if", OpenACCClauseKind::If) 134 .Case("if_present", OpenACCClauseKind::IfPresent) 135 .Case("independent", OpenACCClauseKind::Independent) 136 .Case("link", OpenACCClauseKind::Link) 137 .Case("no_create", OpenACCClauseKind::NoCreate) 138 .Case("num_gangs", OpenACCClauseKind::NumGangs) 139 .Case("num_workers", OpenACCClauseKind::NumWorkers) 140 .Case("nohost", OpenACCClauseKind::NoHost) 141 .Case("present", OpenACCClauseKind::Present) 142 .Case("private", OpenACCClauseKind::Private) 143 .Case("reduction", OpenACCClauseKind::Reduction) 144 .Case("self", OpenACCClauseKind::Self) 145 .Case("seq", OpenACCClauseKind::Seq) 146 .Case("tile", OpenACCClauseKind::Tile) 147 .Case("use_device", OpenACCClauseKind::UseDevice) 148 .Case("vector", OpenACCClauseKind::Vector) 149 .Case("vector_length", OpenACCClauseKind::VectorLength) 150 .Case("wait", OpenACCClauseKind::Wait) 151 .Case("worker", OpenACCClauseKind::Worker) 152 .Default(OpenACCClauseKind::Invalid); 153 } 154 155 // Since 'atomic' is effectively a compound directive, this will decode the 156 // second part of the directive. 157 OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { 158 if (!Tok.is(tok::identifier)) 159 return OpenACCAtomicKind::Invalid; 160 return llvm::StringSwitch<OpenACCAtomicKind>( 161 Tok.getIdentifierInfo()->getName()) 162 .Case("read", OpenACCAtomicKind::Read) 163 .Case("write", OpenACCAtomicKind::Write) 164 .Case("update", OpenACCAtomicKind::Update) 165 .Case("capture", OpenACCAtomicKind::Capture) 166 .Default(OpenACCAtomicKind::Invalid); 167 } 168 169 OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) { 170 if (!Tok.is(tok::identifier)) 171 return OpenACCDefaultClauseKind::Invalid; 172 173 return llvm::StringSwitch<OpenACCDefaultClauseKind>( 174 Tok.getIdentifierInfo()->getName()) 175 .Case("none", OpenACCDefaultClauseKind::None) 176 .Case("present", OpenACCDefaultClauseKind::Present) 177 .Default(OpenACCDefaultClauseKind::Invalid); 178 } 179 180 enum class OpenACCSpecialTokenKind { 181 ReadOnly, 182 DevNum, 183 Queues, 184 Zero, 185 Force, 186 Num, 187 Length, 188 Dim, 189 Static, 190 }; 191 192 bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { 193 if (Tok.is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static) 194 return true; 195 196 if (!Tok.is(tok::identifier)) 197 return false; 198 199 switch (Kind) { 200 case OpenACCSpecialTokenKind::ReadOnly: 201 return Tok.getIdentifierInfo()->isStr("readonly"); 202 case OpenACCSpecialTokenKind::DevNum: 203 return Tok.getIdentifierInfo()->isStr("devnum"); 204 case OpenACCSpecialTokenKind::Queues: 205 return Tok.getIdentifierInfo()->isStr("queues"); 206 case OpenACCSpecialTokenKind::Zero: 207 return Tok.getIdentifierInfo()->isStr("zero"); 208 case OpenACCSpecialTokenKind::Force: 209 return Tok.getIdentifierInfo()->isStr("force"); 210 case OpenACCSpecialTokenKind::Num: 211 return Tok.getIdentifierInfo()->isStr("num"); 212 case OpenACCSpecialTokenKind::Length: 213 return Tok.getIdentifierInfo()->isStr("length"); 214 case OpenACCSpecialTokenKind::Dim: 215 return Tok.getIdentifierInfo()->isStr("dim"); 216 case OpenACCSpecialTokenKind::Static: 217 return Tok.getIdentifierInfo()->isStr("static"); 218 } 219 llvm_unreachable("Unknown 'Kind' Passed"); 220 } 221 222 /// Used for cases where we have a token we want to check against an 223 /// 'identifier-like' token, but don't want to give awkward error messages in 224 /// cases where it is accidentially a keyword. 225 bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) { 226 if (Tok.is(tok::identifier)) 227 return true; 228 229 if (!Tok.isAnnotation() && Tok.getIdentifierInfo() && 230 Tok.getIdentifierInfo()->isKeyword(P.getLangOpts())) 231 return true; 232 233 return false; 234 } 235 236 /// Parses and consumes an identifer followed immediately by a single colon, and 237 /// diagnoses if it is not the 'special token' kind that we require. Used when 238 /// the tag is the only valid value. 239 /// Return 'true' if the special token was matched, false if no special token, 240 /// or an invalid special token was found. 241 template <typename DirOrClauseTy> 242 bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind, 243 DirOrClauseTy DirOrClause) { 244 Token IdentTok = P.getCurToken(); 245 // If this is an identifier-like thing followed by ':', it is one of the 246 // OpenACC 'special' name tags, so consume it. 247 if (isTokenIdentifierOrKeyword(P, IdentTok) && P.NextToken().is(tok::colon)) { 248 P.ConsumeToken(); 249 P.ConsumeToken(); 250 251 if (!isOpenACCSpecialToken(Kind, IdentTok)) { 252 P.Diag(IdentTok, diag::err_acc_invalid_tag_kind) 253 << IdentTok.getIdentifierInfo() << DirOrClause 254 << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>; 255 return false; 256 } 257 258 return true; 259 } 260 261 return false; 262 } 263 264 bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { 265 if (!Tok.is(tok::identifier)) 266 return false; 267 268 switch (Kind) { 269 case OpenACCDirectiveKind::Parallel: 270 return Tok.getIdentifierInfo()->isStr("parallel"); 271 case OpenACCDirectiveKind::Serial: 272 return Tok.getIdentifierInfo()->isStr("serial"); 273 case OpenACCDirectiveKind::Kernels: 274 return Tok.getIdentifierInfo()->isStr("kernels"); 275 case OpenACCDirectiveKind::Data: 276 return Tok.getIdentifierInfo()->isStr("data"); 277 case OpenACCDirectiveKind::HostData: 278 return Tok.getIdentifierInfo()->isStr("host_data"); 279 case OpenACCDirectiveKind::Loop: 280 return Tok.getIdentifierInfo()->isStr("loop"); 281 case OpenACCDirectiveKind::Cache: 282 return Tok.getIdentifierInfo()->isStr("cache"); 283 284 case OpenACCDirectiveKind::ParallelLoop: 285 case OpenACCDirectiveKind::SerialLoop: 286 case OpenACCDirectiveKind::KernelsLoop: 287 case OpenACCDirectiveKind::EnterData: 288 case OpenACCDirectiveKind::ExitData: 289 return false; 290 291 case OpenACCDirectiveKind::Atomic: 292 return Tok.getIdentifierInfo()->isStr("atomic"); 293 case OpenACCDirectiveKind::Routine: 294 return Tok.getIdentifierInfo()->isStr("routine"); 295 case OpenACCDirectiveKind::Declare: 296 return Tok.getIdentifierInfo()->isStr("declare"); 297 case OpenACCDirectiveKind::Init: 298 return Tok.getIdentifierInfo()->isStr("init"); 299 case OpenACCDirectiveKind::Shutdown: 300 return Tok.getIdentifierInfo()->isStr("shutdown"); 301 case OpenACCDirectiveKind::Set: 302 return Tok.getIdentifierInfo()->isStr("set"); 303 case OpenACCDirectiveKind::Update: 304 return Tok.getIdentifierInfo()->isStr("update"); 305 case OpenACCDirectiveKind::Wait: 306 return Tok.getIdentifierInfo()->isStr("wait"); 307 case OpenACCDirectiveKind::Invalid: 308 return false; 309 } 310 llvm_unreachable("Unknown 'Kind' Passed"); 311 } 312 313 OpenACCReductionOperator ParseReductionOperator(Parser &P) { 314 // If there is no colon, treat as if the reduction operator was missing, else 315 // we probably will not recover from it in the case where an expression starts 316 // with one of the operator tokens. 317 if (P.NextToken().isNot(tok::colon)) { 318 P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator); 319 return OpenACCReductionOperator::Invalid; 320 } 321 Token ReductionKindTok = P.getCurToken(); 322 // Consume both the kind and the colon. 323 P.ConsumeToken(); 324 P.ConsumeToken(); 325 326 switch (ReductionKindTok.getKind()) { 327 case tok::plus: 328 return OpenACCReductionOperator::Addition; 329 case tok::star: 330 return OpenACCReductionOperator::Multiplication; 331 case tok::amp: 332 return OpenACCReductionOperator::BitwiseAnd; 333 case tok::pipe: 334 return OpenACCReductionOperator::BitwiseOr; 335 case tok::caret: 336 return OpenACCReductionOperator::BitwiseXOr; 337 case tok::ampamp: 338 return OpenACCReductionOperator::And; 339 case tok::pipepipe: 340 return OpenACCReductionOperator::Or; 341 case tok::identifier: 342 if (ReductionKindTok.getIdentifierInfo()->isStr("max")) 343 return OpenACCReductionOperator::Max; 344 if (ReductionKindTok.getIdentifierInfo()->isStr("min")) 345 return OpenACCReductionOperator::Min; 346 [[fallthrough]]; 347 default: 348 P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator); 349 return OpenACCReductionOperator::Invalid; 350 } 351 llvm_unreachable("Reduction op token kind not caught by 'default'?"); 352 } 353 354 /// Used for cases where we expect an identifier-like token, but don't want to 355 /// give awkward error messages in cases where it is accidentially a keyword. 356 bool expectIdentifierOrKeyword(Parser &P) { 357 Token Tok = P.getCurToken(); 358 359 if (isTokenIdentifierOrKeyword(P, Tok)) 360 return false; 361 362 P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; 363 return true; 364 } 365 366 OpenACCDirectiveKind 367 ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, 368 OpenACCDirectiveKindEx ExtDirKind) { 369 Token SecondTok = P.getCurToken(); 370 371 if (SecondTok.isAnnotation()) { 372 P.Diag(FirstTok, diag::err_acc_invalid_directive) 373 << 0 << FirstTok.getIdentifierInfo(); 374 return OpenACCDirectiveKind::Invalid; 375 } 376 377 // Consume the second name anyway, this way we can continue on without making 378 // this oddly look like a clause. 379 P.ConsumeAnyToken(); 380 381 if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { 382 if (!SecondTok.is(tok::identifier)) 383 P.Diag(SecondTok, diag::err_expected) << tok::identifier; 384 else 385 P.Diag(FirstTok, diag::err_acc_invalid_directive) 386 << 1 << FirstTok.getIdentifierInfo()->getName() 387 << SecondTok.getIdentifierInfo()->getName(); 388 return OpenACCDirectiveKind::Invalid; 389 } 390 391 return ExtDirKind == OpenACCDirectiveKindEx::Enter 392 ? OpenACCDirectiveKind::EnterData 393 : OpenACCDirectiveKind::ExitData; 394 } 395 396 OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) { 397 Token AtomicClauseToken = P.getCurToken(); 398 399 // #pragma acc atomic is equivilent to update: 400 if (AtomicClauseToken.isAnnotation()) 401 return OpenACCAtomicKind::Update; 402 403 OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken); 404 405 // If we don't know what this is, treat it as 'nothing', and treat the rest of 406 // this as a clause list, which, despite being invalid, is likely what the 407 // user was trying to do. 408 if (AtomicKind == OpenACCAtomicKind::Invalid) 409 return OpenACCAtomicKind::Update; 410 411 P.ConsumeToken(); 412 return AtomicKind; 413 } 414 415 // Parse and consume the tokens for OpenACC Directive/Construct kinds. 416 OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { 417 Token FirstTok = P.getCurToken(); 418 419 // Just #pragma acc can get us immediately to the end, make sure we don't 420 // introspect on the spelling before then. 421 if (FirstTok.isNot(tok::identifier)) { 422 P.Diag(FirstTok, diag::err_acc_missing_directive); 423 424 if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 425 P.ConsumeAnyToken(); 426 427 return OpenACCDirectiveKind::Invalid; 428 } 429 430 P.ConsumeToken(); 431 432 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok); 433 434 // OpenACCDirectiveKindEx is meant to be an extended list 435 // over OpenACCDirectiveKind, so any value below Invalid is one of the 436 // OpenACCDirectiveKind values. This switch takes care of all of the extra 437 // parsing required for the Extended values. At the end of this block, 438 // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can 439 // immediately cast it and use it as that. 440 if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) { 441 switch (ExDirKind) { 442 case OpenACCDirectiveKindEx::Invalid: { 443 P.Diag(FirstTok, diag::err_acc_invalid_directive) 444 << 0 << FirstTok.getIdentifierInfo(); 445 return OpenACCDirectiveKind::Invalid; 446 } 447 case OpenACCDirectiveKindEx::Enter: 448 case OpenACCDirectiveKindEx::Exit: 449 return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind); 450 } 451 } 452 453 OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind); 454 455 // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any 456 // other attempt at a combined construct will be diagnosed as an invalid 457 // clause. 458 Token SecondTok = P.getCurToken(); 459 if (!SecondTok.isAnnotation() && 460 isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) { 461 switch (DirKind) { 462 default: 463 // Nothing to do except in the below cases, as they should be diagnosed as 464 // a clause. 465 break; 466 case OpenACCDirectiveKind::Parallel: 467 P.ConsumeToken(); 468 return OpenACCDirectiveKind::ParallelLoop; 469 case OpenACCDirectiveKind::Serial: 470 P.ConsumeToken(); 471 return OpenACCDirectiveKind::SerialLoop; 472 case OpenACCDirectiveKind::Kernels: 473 P.ConsumeToken(); 474 return OpenACCDirectiveKind::KernelsLoop; 475 } 476 } 477 478 return DirKind; 479 } 480 481 enum ClauseParensKind { 482 None, 483 Optional, 484 Required 485 }; 486 487 ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind, 488 OpenACCClauseKind Kind) { 489 switch (Kind) { 490 case OpenACCClauseKind::Self: 491 return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required 492 : ClauseParensKind::Optional; 493 case OpenACCClauseKind::Async: 494 case OpenACCClauseKind::Worker: 495 case OpenACCClauseKind::Vector: 496 case OpenACCClauseKind::Gang: 497 case OpenACCClauseKind::Wait: 498 return ClauseParensKind::Optional; 499 500 case OpenACCClauseKind::Default: 501 case OpenACCClauseKind::If: 502 case OpenACCClauseKind::Create: 503 case OpenACCClauseKind::PCreate: 504 case OpenACCClauseKind::PresentOrCreate: 505 case OpenACCClauseKind::Copy: 506 case OpenACCClauseKind::PCopy: 507 case OpenACCClauseKind::PresentOrCopy: 508 case OpenACCClauseKind::CopyIn: 509 case OpenACCClauseKind::PCopyIn: 510 case OpenACCClauseKind::PresentOrCopyIn: 511 case OpenACCClauseKind::CopyOut: 512 case OpenACCClauseKind::PCopyOut: 513 case OpenACCClauseKind::PresentOrCopyOut: 514 case OpenACCClauseKind::UseDevice: 515 case OpenACCClauseKind::NoCreate: 516 case OpenACCClauseKind::Present: 517 case OpenACCClauseKind::DevicePtr: 518 case OpenACCClauseKind::Attach: 519 case OpenACCClauseKind::Detach: 520 case OpenACCClauseKind::Private: 521 case OpenACCClauseKind::FirstPrivate: 522 case OpenACCClauseKind::Delete: 523 case OpenACCClauseKind::DeviceResident: 524 case OpenACCClauseKind::Device: 525 case OpenACCClauseKind::Link: 526 case OpenACCClauseKind::Host: 527 case OpenACCClauseKind::Reduction: 528 case OpenACCClauseKind::Collapse: 529 case OpenACCClauseKind::Bind: 530 case OpenACCClauseKind::VectorLength: 531 case OpenACCClauseKind::NumGangs: 532 case OpenACCClauseKind::NumWorkers: 533 case OpenACCClauseKind::DeviceNum: 534 case OpenACCClauseKind::DefaultAsync: 535 case OpenACCClauseKind::DeviceType: 536 case OpenACCClauseKind::DType: 537 case OpenACCClauseKind::Tile: 538 return ClauseParensKind::Required; 539 540 case OpenACCClauseKind::Auto: 541 case OpenACCClauseKind::Finalize: 542 case OpenACCClauseKind::IfPresent: 543 case OpenACCClauseKind::Independent: 544 case OpenACCClauseKind::Invalid: 545 case OpenACCClauseKind::NoHost: 546 case OpenACCClauseKind::Seq: 547 return ClauseParensKind::None; 548 } 549 llvm_unreachable("Unhandled clause kind"); 550 } 551 552 bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind, 553 OpenACCClauseKind Kind) { 554 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional; 555 } 556 557 bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind, 558 OpenACCClauseKind Kind) { 559 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required; 560 } 561 562 // Skip until we see the end of pragma token, but don't consume it. This is us 563 // just giving up on the rest of the pragma so we can continue executing. We 564 // have to do this because 'SkipUntil' considers paren balancing, which isn't 565 // what we want. 566 void SkipUntilEndOfDirective(Parser &P) { 567 while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 568 P.ConsumeAnyToken(); 569 } 570 571 bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) { 572 switch (DirKind) { 573 default: 574 case OpenACCDirectiveKind::EnterData: 575 case OpenACCDirectiveKind::ExitData: 576 case OpenACCDirectiveKind::Wait: 577 case OpenACCDirectiveKind::Init: 578 case OpenACCDirectiveKind::Shutdown: 579 return false; 580 case OpenACCDirectiveKind::Parallel: 581 case OpenACCDirectiveKind::Serial: 582 case OpenACCDirectiveKind::Kernels: 583 case OpenACCDirectiveKind::ParallelLoop: 584 case OpenACCDirectiveKind::SerialLoop: 585 case OpenACCDirectiveKind::KernelsLoop: 586 case OpenACCDirectiveKind::Loop: 587 case OpenACCDirectiveKind::Data: 588 case OpenACCDirectiveKind::HostData: 589 return true; 590 } 591 llvm_unreachable("Unhandled directive->assoc stmt"); 592 } 593 594 unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) { 595 switch (DirKind) { 596 case OpenACCDirectiveKind::Parallel: 597 case OpenACCDirectiveKind::Serial: 598 case OpenACCDirectiveKind::Kernels: 599 case OpenACCDirectiveKind::ParallelLoop: 600 case OpenACCDirectiveKind::SerialLoop: 601 case OpenACCDirectiveKind::KernelsLoop: 602 // Mark this as a BreakScope/ContinueScope as well as a compute construct 603 // so that we can diagnose trying to 'break'/'continue' inside of one. 604 return Scope::BreakScope | Scope::ContinueScope | 605 Scope::OpenACCComputeConstructScope; 606 case OpenACCDirectiveKind::Data: 607 case OpenACCDirectiveKind::EnterData: 608 case OpenACCDirectiveKind::ExitData: 609 case OpenACCDirectiveKind::HostData: 610 case OpenACCDirectiveKind::Wait: 611 case OpenACCDirectiveKind::Init: 612 case OpenACCDirectiveKind::Shutdown: 613 return 0; 614 case OpenACCDirectiveKind::Invalid: 615 llvm_unreachable("Shouldn't be creating a scope for an invalid construct"); 616 default: 617 break; 618 } 619 return 0; 620 } 621 622 } // namespace 623 624 Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() { 625 return {nullptr, OpenACCParseCanContinue::Can}; 626 } 627 628 Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() { 629 return {nullptr, OpenACCParseCanContinue::Cannot}; 630 } 631 632 Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) { 633 return {Clause, OpenACCParseCanContinue::Can}; 634 } 635 636 ExprResult Parser::ParseOpenACCConditionExpr() { 637 // FIXME: It isn't clear if the spec saying 'condition' means the same as 638 // it does in an if/while/etc (See ParseCXXCondition), however as it was 639 // written with Fortran/C in mind, we're going to assume it just means an 640 // 'expression evaluating to boolean'. 641 ExprResult ER = getActions().CorrectDelayedTyposInExpr(ParseExpression()); 642 643 if (!ER.isUsable()) 644 return ER; 645 646 Sema::ConditionResult R = 647 getActions().ActOnCondition(getCurScope(), ER.get()->getExprLoc(), 648 ER.get(), Sema::ConditionKind::Boolean); 649 650 return R.isInvalid() ? ExprError() : R.get().second; 651 } 652 653 // OpenACC 3.3, section 1.7: 654 // To simplify the specification and convey appropriate constraint information, 655 // a pqr-list is a comma-separated list of pdr items. The one exception is a 656 // clause-list, which is a list of one or more clauses optionally separated by 657 // commas. 658 SmallVector<OpenACCClause *> 659 Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { 660 SmallVector<OpenACCClause *> Clauses; 661 bool FirstClause = true; 662 while (getCurToken().isNot(tok::annot_pragma_openacc_end)) { 663 // Comma is optional in a clause-list. 664 if (!FirstClause && getCurToken().is(tok::comma)) 665 ConsumeToken(); 666 FirstClause = false; 667 668 OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind); 669 if (OpenACCClause *Clause = Result.getPointer()) { 670 Clauses.push_back(Clause); 671 } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) { 672 // Recovering from a bad clause is really difficult, so we just give up on 673 // error. 674 SkipUntilEndOfDirective(*this); 675 return Clauses; 676 } 677 } 678 return Clauses; 679 } 680 681 Parser::OpenACCIntExprParseResult 682 Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, 683 SourceLocation Loc) { 684 ExprResult ER = ParseAssignmentExpression(); 685 686 // If the actual parsing failed, we don't know the state of the parse, so 687 // don't try to continue. 688 if (!ER.isUsable()) 689 return {ER, OpenACCParseCanContinue::Cannot}; 690 691 // Parsing can continue after the initial assignment expression parsing, so 692 // even if there was a typo, we can continue. 693 ER = getActions().CorrectDelayedTyposInExpr(ER); 694 if (!ER.isUsable()) 695 return {ER, OpenACCParseCanContinue::Can}; 696 697 return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()), 698 OpenACCParseCanContinue::Can}; 699 } 700 701 bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, 702 OpenACCClauseKind CK, SourceLocation Loc, 703 llvm::SmallVectorImpl<Expr *> &IntExprs) { 704 OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc); 705 706 if (!CurResult.first.isUsable() && 707 CurResult.second == OpenACCParseCanContinue::Cannot) { 708 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 709 Parser::StopBeforeMatch); 710 return true; 711 } 712 713 IntExprs.push_back(CurResult.first.get()); 714 715 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 716 ExpectAndConsume(tok::comma); 717 718 CurResult = ParseOpenACCIntExpr(DK, CK, Loc); 719 720 if (!CurResult.first.isUsable() && 721 CurResult.second == OpenACCParseCanContinue::Cannot) { 722 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 723 Parser::StopBeforeMatch); 724 return true; 725 } 726 IntExprs.push_back(CurResult.first.get()); 727 } 728 return false; 729 } 730 731 /// OpenACC 3.3 Section 2.4: 732 /// The argument to the device_type clause is a comma-separated list of one or 733 /// more device architecture name identifiers, or an asterisk. 734 /// 735 /// The syntax of the device_type clause is 736 /// device_type( * ) 737 /// device_type( device-type-list ) 738 /// 739 /// The device_type clause may be abbreviated to dtype. 740 bool Parser::ParseOpenACCDeviceTypeList( 741 llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs) { 742 743 if (expectIdentifierOrKeyword(*this)) { 744 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 745 Parser::StopBeforeMatch); 746 return true; 747 } 748 IdentifierInfo *Ident = getCurToken().getIdentifierInfo(); 749 Archs.emplace_back(Ident, ConsumeToken()); 750 751 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 752 ExpectAndConsume(tok::comma); 753 754 if (expectIdentifierOrKeyword(*this)) { 755 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 756 Parser::StopBeforeMatch); 757 return true; 758 } 759 Ident = getCurToken().getIdentifierInfo(); 760 Archs.emplace_back(Ident, ConsumeToken()); 761 } 762 return false; 763 } 764 765 /// OpenACC 3.3 Section 2.9: 766 /// size-expr is one of: 767 // * 768 // int-expr 769 // Note that this is specified under 'gang-arg-list', but also applies to 'tile' 770 // via reference. 771 ExprResult Parser::ParseOpenACCSizeExpr(OpenACCClauseKind CK) { 772 // The size-expr ends up being ambiguous when only looking at the current 773 // token, as it could be a deref of a variable/expression. 774 if (getCurToken().is(tok::star) && 775 NextToken().isOneOf(tok::comma, tok::r_paren, 776 tok::annot_pragma_openacc_end)) { 777 SourceLocation AsteriskLoc = ConsumeToken(); 778 return getActions().OpenACC().ActOnOpenACCAsteriskSizeExpr(AsteriskLoc); 779 } 780 781 ExprResult SizeExpr = 782 getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 783 784 if (!SizeExpr.isUsable()) 785 return SizeExpr; 786 787 SizeExpr = getActions().OpenACC().ActOnIntExpr( 788 OpenACCDirectiveKind::Invalid, CK, SizeExpr.get()->getBeginLoc(), 789 SizeExpr.get()); 790 791 return SizeExpr; 792 } 793 794 bool Parser::ParseOpenACCSizeExprList( 795 OpenACCClauseKind CK, llvm::SmallVectorImpl<Expr *> &SizeExprs) { 796 ExprResult SizeExpr = ParseOpenACCSizeExpr(CK); 797 if (!SizeExpr.isUsable()) { 798 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 799 Parser::StopBeforeMatch); 800 return true; 801 } 802 803 SizeExprs.push_back(SizeExpr.get()); 804 805 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 806 ExpectAndConsume(tok::comma); 807 808 SizeExpr = ParseOpenACCSizeExpr(CK); 809 if (!SizeExpr.isUsable()) { 810 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 811 Parser::StopBeforeMatch); 812 return true; 813 } 814 SizeExprs.push_back(SizeExpr.get()); 815 } 816 return false; 817 } 818 819 /// OpenACC 3.3 Section 2.9: 820 /// 821 /// where gang-arg is one of: 822 /// [num:]int-expr 823 /// dim:int-expr 824 /// static:size-expr 825 Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { 826 827 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) && 828 NextToken().is(tok::colon)) { 829 // 'static' just takes a size-expr, which is an int-expr or an asterisk. 830 ConsumeToken(); 831 ConsumeToken(); 832 ExprResult Res = ParseOpenACCSizeExpr(OpenACCClauseKind::Gang); 833 return {OpenACCGangKind::Static, Res}; 834 } 835 836 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) && 837 NextToken().is(tok::colon)) { 838 ConsumeToken(); 839 ConsumeToken(); 840 // Parse this as a const-expression, and we'll check its integer-ness/value 841 // in CheckGangExpr. 842 ExprResult Res = 843 getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 844 return {OpenACCGangKind::Dim, Res}; 845 } 846 847 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) && 848 NextToken().is(tok::colon)) { 849 ConsumeToken(); 850 ConsumeToken(); 851 // Fallthrough to the 'int-expr' handling for when 'num' is omitted. 852 } 853 854 // This is just the 'num' case where 'num' is optional. 855 ExprResult Res = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 856 OpenACCClauseKind::Gang, GangLoc) 857 .first; 858 return {OpenACCGangKind::Num, Res}; 859 } 860 861 bool Parser::ParseOpenACCGangArgList( 862 SourceLocation GangLoc, llvm::SmallVectorImpl<OpenACCGangKind> &GKs, 863 llvm::SmallVectorImpl<Expr *> &IntExprs) { 864 865 Parser::OpenACCGangArgRes Res = ParseOpenACCGangArg(GangLoc); 866 if (!Res.second.isUsable()) { 867 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 868 Parser::StopBeforeMatch); 869 return true; 870 } 871 872 GKs.push_back(Res.first); 873 IntExprs.push_back(Res.second.get()); 874 875 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 876 ExpectAndConsume(tok::comma); 877 878 Res = ParseOpenACCGangArg(GangLoc); 879 if (!Res.second.isUsable()) { 880 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 881 Parser::StopBeforeMatch); 882 return true; 883 } 884 885 GKs.push_back(Res.first); 886 IntExprs.push_back(Res.second.get()); 887 } 888 return false; 889 } 890 891 // The OpenACC Clause List is a comma or space-delimited list of clauses (see 892 // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't 893 // really have its owner grammar and each individual one has its own definition. 894 // However, they all are named with a single-identifier (or auto/default!) 895 // token, followed in some cases by either braces or parens. 896 Parser::OpenACCClauseParseResult 897 Parser::ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses, 898 OpenACCDirectiveKind DirKind) { 899 // A number of clause names are actually keywords, so accept a keyword that 900 // can be converted to a name. 901 if (expectIdentifierOrKeyword(*this)) 902 return OpenACCCannotContinue(); 903 904 OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken()); 905 906 if (Kind == OpenACCClauseKind::Invalid) { 907 Diag(getCurToken(), diag::err_acc_invalid_clause) 908 << getCurToken().getIdentifierInfo(); 909 return OpenACCCannotContinue(); 910 } 911 912 // Consume the clause name. 913 SourceLocation ClauseLoc = ConsumeToken(); 914 915 return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc); 916 } 917 918 Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( 919 ArrayRef<const OpenACCClause *> ExistingClauses, 920 OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind, 921 SourceLocation ClauseLoc) { 922 BalancedDelimiterTracker Parens(*this, tok::l_paren, 923 tok::annot_pragma_openacc_end); 924 SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc); 925 926 if (ClauseHasRequiredParens(DirKind, ClauseKind)) { 927 if (Parens.expectAndConsume()) { 928 // We are missing a paren, so assume that the person just forgot the 929 // parameter. Return 'false' so we try to continue on and parse the next 930 // clause. 931 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, 932 Parser::StopBeforeMatch); 933 return OpenACCCanContinue(); 934 } 935 ParsedClause.setLParenLoc(Parens.getOpenLocation()); 936 937 switch (ClauseKind) { 938 case OpenACCClauseKind::Default: { 939 Token DefKindTok = getCurToken(); 940 941 if (expectIdentifierOrKeyword(*this)) { 942 Parens.skipToEnd(); 943 return OpenACCCanContinue(); 944 } 945 946 ConsumeToken(); 947 948 OpenACCDefaultClauseKind DefKind = 949 getOpenACCDefaultClauseKind(DefKindTok); 950 951 if (DefKind == OpenACCDefaultClauseKind::Invalid) { 952 Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); 953 Parens.skipToEnd(); 954 return OpenACCCanContinue(); 955 } 956 957 ParsedClause.setDefaultDetails(DefKind); 958 break; 959 } 960 case OpenACCClauseKind::If: { 961 ExprResult CondExpr = ParseOpenACCConditionExpr(); 962 ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() 963 : nullptr); 964 965 if (CondExpr.isInvalid()) { 966 Parens.skipToEnd(); 967 return OpenACCCanContinue(); 968 } 969 970 break; 971 } 972 case OpenACCClauseKind::CopyIn: 973 case OpenACCClauseKind::PCopyIn: 974 case OpenACCClauseKind::PresentOrCopyIn: { 975 bool IsReadOnly = tryParseAndConsumeSpecialTokenKind( 976 *this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind); 977 ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 978 IsReadOnly, 979 /*IsZero=*/false); 980 break; 981 } 982 case OpenACCClauseKind::Create: 983 case OpenACCClauseKind::PCreate: 984 case OpenACCClauseKind::PresentOrCreate: 985 case OpenACCClauseKind::CopyOut: 986 case OpenACCClauseKind::PCopyOut: 987 case OpenACCClauseKind::PresentOrCopyOut: { 988 bool IsZero = tryParseAndConsumeSpecialTokenKind( 989 *this, OpenACCSpecialTokenKind::Zero, ClauseKind); 990 ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 991 /*IsReadOnly=*/false, IsZero); 992 break; 993 } 994 case OpenACCClauseKind::Reduction: { 995 // If we're missing a clause-kind (or it is invalid), see if we can parse 996 // the var-list anyway. 997 OpenACCReductionOperator Op = ParseReductionOperator(*this); 998 ParsedClause.setReductionDetails(Op, ParseOpenACCVarList(ClauseKind)); 999 break; 1000 } 1001 case OpenACCClauseKind::Self: 1002 // The 'self' clause is a var-list instead of a 'condition' in the case of 1003 // the 'update' clause, so we have to handle it here. Use an assert to 1004 // make sure we get the right differentiator. 1005 assert(DirKind == OpenACCDirectiveKind::Update); 1006 [[fallthrough]]; 1007 case OpenACCClauseKind::Device: 1008 case OpenACCClauseKind::Host: 1009 ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 1010 /*IsReadOnly=*/false, /*IsZero=*/false); 1011 break; 1012 case OpenACCClauseKind::DeviceResident: 1013 case OpenACCClauseKind::Link: 1014 ParseOpenACCVarList(ClauseKind); 1015 break; 1016 case OpenACCClauseKind::Attach: 1017 case OpenACCClauseKind::Delete: 1018 case OpenACCClauseKind::Detach: 1019 case OpenACCClauseKind::DevicePtr: 1020 case OpenACCClauseKind::UseDevice: 1021 ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 1022 /*IsReadOnly=*/false, /*IsZero=*/false); 1023 break; 1024 case OpenACCClauseKind::Copy: 1025 case OpenACCClauseKind::PCopy: 1026 case OpenACCClauseKind::PresentOrCopy: 1027 case OpenACCClauseKind::FirstPrivate: 1028 case OpenACCClauseKind::NoCreate: 1029 case OpenACCClauseKind::Present: 1030 case OpenACCClauseKind::Private: 1031 ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 1032 /*IsReadOnly=*/false, /*IsZero=*/false); 1033 break; 1034 case OpenACCClauseKind::Collapse: { 1035 bool HasForce = tryParseAndConsumeSpecialTokenKind( 1036 *this, OpenACCSpecialTokenKind::Force, ClauseKind); 1037 ExprResult LoopCount = 1038 getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 1039 if (LoopCount.isInvalid()) { 1040 Parens.skipToEnd(); 1041 return OpenACCCanContinue(); 1042 } 1043 1044 LoopCount = getActions().OpenACC().ActOnIntExpr( 1045 OpenACCDirectiveKind::Invalid, ClauseKind, 1046 LoopCount.get()->getBeginLoc(), LoopCount.get()); 1047 1048 if (LoopCount.isInvalid()) { 1049 Parens.skipToEnd(); 1050 return OpenACCCanContinue(); 1051 } 1052 1053 ParsedClause.setCollapseDetails(HasForce, LoopCount.get()); 1054 break; 1055 } 1056 case OpenACCClauseKind::Bind: { 1057 ExprResult BindArg = ParseOpenACCBindClauseArgument(); 1058 if (BindArg.isInvalid()) { 1059 Parens.skipToEnd(); 1060 return OpenACCCanContinue(); 1061 } 1062 break; 1063 } 1064 case OpenACCClauseKind::NumGangs: { 1065 llvm::SmallVector<Expr *> IntExprs; 1066 1067 if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid, 1068 OpenACCClauseKind::NumGangs, ClauseLoc, 1069 IntExprs)) { 1070 Parens.skipToEnd(); 1071 return OpenACCCanContinue(); 1072 } 1073 ParsedClause.setIntExprDetails(std::move(IntExprs)); 1074 break; 1075 } 1076 case OpenACCClauseKind::NumWorkers: 1077 case OpenACCClauseKind::DeviceNum: 1078 case OpenACCClauseKind::DefaultAsync: 1079 case OpenACCClauseKind::VectorLength: { 1080 ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 1081 ClauseKind, ClauseLoc) 1082 .first; 1083 if (IntExpr.isInvalid()) { 1084 Parens.skipToEnd(); 1085 return OpenACCCanContinue(); 1086 } 1087 1088 ParsedClause.setIntExprDetails(IntExpr.get()); 1089 break; 1090 } 1091 case OpenACCClauseKind::DType: 1092 case OpenACCClauseKind::DeviceType: { 1093 llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> Archs; 1094 if (getCurToken().is(tok::star)) { 1095 // FIXME: We want to mark that this is an 'everything else' type of 1096 // device_type in Sema. 1097 ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}}); 1098 } else if (!ParseOpenACCDeviceTypeList(Archs)) { 1099 ParsedClause.setDeviceTypeDetails(std::move(Archs)); 1100 } else { 1101 Parens.skipToEnd(); 1102 return OpenACCCanContinue(); 1103 } 1104 break; 1105 } 1106 case OpenACCClauseKind::Tile: { 1107 llvm::SmallVector<Expr *> SizeExprs; 1108 if (ParseOpenACCSizeExprList(OpenACCClauseKind::Tile, SizeExprs)) { 1109 Parens.skipToEnd(); 1110 return OpenACCCanContinue(); 1111 } 1112 1113 ParsedClause.setIntExprDetails(std::move(SizeExprs)); 1114 break; 1115 } 1116 default: 1117 llvm_unreachable("Not a required parens type?"); 1118 } 1119 1120 ParsedClause.setEndLoc(getCurToken().getLocation()); 1121 1122 if (Parens.consumeClose()) 1123 return OpenACCCannotContinue(); 1124 1125 } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) { 1126 if (!Parens.consumeOpen()) { 1127 ParsedClause.setLParenLoc(Parens.getOpenLocation()); 1128 switch (ClauseKind) { 1129 case OpenACCClauseKind::Self: { 1130 assert(DirKind != OpenACCDirectiveKind::Update); 1131 ExprResult CondExpr = ParseOpenACCConditionExpr(); 1132 ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() 1133 : nullptr); 1134 1135 if (CondExpr.isInvalid()) { 1136 Parens.skipToEnd(); 1137 return OpenACCCanContinue(); 1138 } 1139 break; 1140 } 1141 case OpenACCClauseKind::Vector: 1142 case OpenACCClauseKind::Worker: { 1143 tryParseAndConsumeSpecialTokenKind(*this, 1144 ClauseKind == 1145 OpenACCClauseKind::Vector 1146 ? OpenACCSpecialTokenKind::Length 1147 : OpenACCSpecialTokenKind::Num, 1148 ClauseKind); 1149 ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 1150 ClauseKind, ClauseLoc) 1151 .first; 1152 if (IntExpr.isInvalid()) { 1153 Parens.skipToEnd(); 1154 return OpenACCCanContinue(); 1155 } 1156 ParsedClause.setIntExprDetails(IntExpr.get()); 1157 break; 1158 } 1159 case OpenACCClauseKind::Async: { 1160 ExprResult AsyncArg = 1161 ParseOpenACCAsyncArgument(OpenACCDirectiveKind::Invalid, 1162 OpenACCClauseKind::Async, ClauseLoc) 1163 .first; 1164 ParsedClause.setIntExprDetails(AsyncArg.isUsable() ? AsyncArg.get() 1165 : nullptr); 1166 if (AsyncArg.isInvalid()) { 1167 Parens.skipToEnd(); 1168 return OpenACCCanContinue(); 1169 } 1170 break; 1171 } 1172 case OpenACCClauseKind::Gang: { 1173 llvm::SmallVector<OpenACCGangKind> GKs; 1174 llvm::SmallVector<Expr *> IntExprs; 1175 if (ParseOpenACCGangArgList(ClauseLoc, GKs, IntExprs)) { 1176 Parens.skipToEnd(); 1177 return OpenACCCanContinue(); 1178 } 1179 ParsedClause.setGangDetails(std::move(GKs), std::move(IntExprs)); 1180 break; 1181 } 1182 case OpenACCClauseKind::Wait: { 1183 OpenACCWaitParseInfo Info = 1184 ParseOpenACCWaitArgument(ClauseLoc, 1185 /*IsDirective=*/false); 1186 if (Info.Failed) { 1187 Parens.skipToEnd(); 1188 return OpenACCCanContinue(); 1189 } 1190 1191 ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc, 1192 std::move(Info.QueueIdExprs)); 1193 break; 1194 } 1195 default: 1196 llvm_unreachable("Not an optional parens type?"); 1197 } 1198 ParsedClause.setEndLoc(getCurToken().getLocation()); 1199 if (Parens.consumeClose()) 1200 return OpenACCCannotContinue(); 1201 } else { 1202 // If we have optional parens, make sure we set the end-location to the 1203 // clause, as we are a 'single token' clause. 1204 ParsedClause.setEndLoc(ClauseLoc); 1205 } 1206 } else { 1207 ParsedClause.setEndLoc(ClauseLoc); 1208 } 1209 return OpenACCSuccess( 1210 Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause)); 1211 } 1212 1213 /// OpenACC 3.3 section 2.16: 1214 /// In this section and throughout the specification, the term async-argument 1215 /// means a nonnegative scalar integer expression (int for C or C++, integer for 1216 /// Fortran), or one of the special values acc_async_noval or acc_async_sync, as 1217 /// defined in the C header file and the Fortran openacc module. The special 1218 /// values are negative values, so as not to conflict with a user-specified 1219 /// nonnegative async-argument. 1220 Parser::OpenACCIntExprParseResult 1221 Parser::ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, OpenACCClauseKind CK, 1222 SourceLocation Loc) { 1223 return ParseOpenACCIntExpr(DK, CK, Loc); 1224 } 1225 1226 /// OpenACC 3.3, section 2.16: 1227 /// In this section and throughout the specification, the term wait-argument 1228 /// means: 1229 /// [ devnum : int-expr : ] [ queues : ] async-argument-list 1230 Parser::OpenACCWaitParseInfo 1231 Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) { 1232 OpenACCWaitParseInfo Result; 1233 // [devnum : int-expr : ] 1234 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && 1235 NextToken().is(tok::colon)) { 1236 // Consume devnum. 1237 ConsumeToken(); 1238 // Consume colon. 1239 ConsumeToken(); 1240 1241 OpenACCIntExprParseResult Res = ParseOpenACCIntExpr( 1242 IsDirective ? OpenACCDirectiveKind::Wait 1243 : OpenACCDirectiveKind::Invalid, 1244 IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, 1245 Loc); 1246 if (Res.first.isInvalid() && 1247 Res.second == OpenACCParseCanContinue::Cannot) { 1248 Result.Failed = true; 1249 return Result; 1250 } 1251 1252 if (ExpectAndConsume(tok::colon)) { 1253 Result.Failed = true; 1254 return Result; 1255 } 1256 1257 Result.DevNumExpr = Res.first.get(); 1258 } 1259 1260 // [ queues : ] 1261 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && 1262 NextToken().is(tok::colon)) { 1263 // Consume queues. 1264 Result.QueuesLoc = ConsumeToken(); 1265 // Consume colon. 1266 ConsumeToken(); 1267 } 1268 1269 // OpenACC 3.3, section 2.16: 1270 // the term 'async-argument' means a nonnegative scalar integer expression, or 1271 // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined 1272 // in the C header file and the Fortran opacc module. 1273 bool FirstArg = true; 1274 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 1275 if (!FirstArg) { 1276 if (ExpectAndConsume(tok::comma)) { 1277 Result.Failed = true; 1278 return Result; 1279 } 1280 } 1281 FirstArg = false; 1282 1283 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument( 1284 IsDirective ? OpenACCDirectiveKind::Wait 1285 : OpenACCDirectiveKind::Invalid, 1286 IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, 1287 Loc); 1288 1289 if (Res.first.isInvalid() && 1290 Res.second == OpenACCParseCanContinue::Cannot) { 1291 Result.Failed = true; 1292 return Result; 1293 } 1294 1295 if (Res.first.isUsable()) 1296 Result.QueueIdExprs.push_back(Res.first.get()); 1297 } 1298 1299 return Result; 1300 } 1301 1302 ExprResult Parser::ParseOpenACCIDExpression() { 1303 ExprResult Res; 1304 if (getLangOpts().CPlusPlus) { 1305 Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true); 1306 } else { 1307 // There isn't anything quite the same as ParseCXXIdExpression for C, so we 1308 // need to get the identifier, then call into Sema ourselves. 1309 1310 if (Tok.isNot(tok::identifier)) { 1311 Diag(Tok, diag::err_expected) << tok::identifier; 1312 return ExprError(); 1313 } 1314 1315 Token FuncName = getCurToken(); 1316 UnqualifiedId Name; 1317 CXXScopeSpec ScopeSpec; 1318 SourceLocation TemplateKWLoc; 1319 Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken()); 1320 1321 // Ensure this is a valid identifier. We don't accept causing implicit 1322 // function declarations per the spec, so always claim to not have trailing 1323 // L Paren. 1324 Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, 1325 Name, /*HasTrailingLParen=*/false, 1326 /*isAddressOfOperand=*/false); 1327 } 1328 1329 return getActions().CorrectDelayedTyposInExpr(Res); 1330 } 1331 1332 ExprResult Parser::ParseOpenACCBindClauseArgument() { 1333 // OpenACC 3.3 section 2.15: 1334 // The bind clause specifies the name to use when calling the procedure on a 1335 // device other than the host. If the name is specified as an identifier, it 1336 // is called as if that name were specified in the language being compiled. If 1337 // the name is specified as a string, the string is used for the procedure 1338 // name unmodified. 1339 if (getCurToken().is(tok::r_paren)) { 1340 Diag(getCurToken(), diag::err_acc_incorrect_bind_arg); 1341 return ExprError(); 1342 } 1343 1344 if (tok::isStringLiteral(getCurToken().getKind())) 1345 return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression( 1346 /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true)); 1347 1348 return ParseOpenACCIDExpression(); 1349 } 1350 1351 /// OpenACC 3.3, section 1.6: 1352 /// In this spec, a 'var' (in italics) is one of the following: 1353 /// - a variable name (a scalar, array, or composite variable name) 1354 /// - a subarray specification with subscript ranges 1355 /// - an array element 1356 /// - a member of a composite variable 1357 /// - a common block name between slashes (fortran only) 1358 Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCClauseKind CK) { 1359 OpenACCArraySectionRAII ArraySections(*this); 1360 1361 ExprResult Res = ParseAssignmentExpression(); 1362 if (!Res.isUsable()) 1363 return {Res, OpenACCParseCanContinue::Cannot}; 1364 1365 Res = getActions().CorrectDelayedTyposInExpr(Res.get()); 1366 if (!Res.isUsable()) 1367 return {Res, OpenACCParseCanContinue::Can}; 1368 1369 Res = getActions().OpenACC().ActOnVar(CK, Res.get()); 1370 1371 return {Res, OpenACCParseCanContinue::Can}; 1372 } 1373 1374 llvm::SmallVector<Expr *> Parser::ParseOpenACCVarList(OpenACCClauseKind CK) { 1375 llvm::SmallVector<Expr *> Vars; 1376 1377 auto [Res, CanContinue] = ParseOpenACCVar(CK); 1378 if (Res.isUsable()) { 1379 Vars.push_back(Res.get()); 1380 } else if (CanContinue == OpenACCParseCanContinue::Cannot) { 1381 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch); 1382 return Vars; 1383 } 1384 1385 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 1386 ExpectAndConsume(tok::comma); 1387 1388 auto [Res, CanContinue] = ParseOpenACCVar(CK); 1389 1390 if (Res.isUsable()) { 1391 Vars.push_back(Res.get()); 1392 } else if (CanContinue == OpenACCParseCanContinue::Cannot) { 1393 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch); 1394 return Vars; 1395 } 1396 } 1397 return Vars; 1398 } 1399 1400 /// OpenACC 3.3, section 2.10: 1401 /// In C and C++, the syntax of the cache directive is: 1402 /// 1403 /// #pragma acc cache ([readonly:]var-list) new-line 1404 void Parser::ParseOpenACCCacheVarList() { 1405 // If this is the end of the line, just return 'false' and count on the close 1406 // paren diagnostic to catch the issue. 1407 if (getCurToken().isAnnotation()) 1408 return; 1409 1410 // The VarList is an optional `readonly:` followed by a list of a variable 1411 // specifications. Consume something that looks like a 'tag', and diagnose if 1412 // it isn't 'readonly'. 1413 if (tryParseAndConsumeSpecialTokenKind(*this, 1414 OpenACCSpecialTokenKind::ReadOnly, 1415 OpenACCDirectiveKind::Cache)) { 1416 // FIXME: Record that this is a 'readonly' so that we can use that during 1417 // Sema/AST generation. 1418 } 1419 1420 // ParseOpenACCVarList should leave us before a r-paren, so no need to skip 1421 // anything here. 1422 ParseOpenACCVarList(OpenACCClauseKind::Invalid); 1423 } 1424 1425 Parser::OpenACCDirectiveParseInfo 1426 Parser::ParseOpenACCDirective() { 1427 SourceLocation StartLoc = ConsumeAnnotationToken(); 1428 SourceLocation DirLoc = getCurToken().getLocation(); 1429 OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); 1430 Parser::OpenACCWaitParseInfo WaitInfo; 1431 1432 getActions().OpenACC().ActOnConstruct(DirKind, DirLoc); 1433 1434 // Once we've parsed the construct/directive name, some have additional 1435 // specifiers that need to be taken care of. Atomic has an 'atomic-clause' 1436 // that needs to be parsed. 1437 if (DirKind == OpenACCDirectiveKind::Atomic) 1438 ParseOpenACCAtomicKind(*this); 1439 1440 // We've successfully parsed the construct/directive name, however a few of 1441 // the constructs have optional parens that contain further details. 1442 BalancedDelimiterTracker T(*this, tok::l_paren, 1443 tok::annot_pragma_openacc_end); 1444 1445 if (!T.consumeOpen()) { 1446 switch (DirKind) { 1447 default: 1448 Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren); 1449 T.skipToEnd(); 1450 break; 1451 case OpenACCDirectiveKind::Routine: { 1452 // Routine has an optional paren-wrapped name of a function in the local 1453 // scope. We parse the name, emitting any diagnostics 1454 ExprResult RoutineName = ParseOpenACCIDExpression(); 1455 // If the routine name is invalid, just skip until the closing paren to 1456 // recover more gracefully. 1457 if (RoutineName.isInvalid()) 1458 T.skipToEnd(); 1459 else 1460 T.consumeClose(); 1461 break; 1462 } 1463 case OpenACCDirectiveKind::Cache: 1464 ParseOpenACCCacheVarList(); 1465 // The ParseOpenACCCacheVarList function manages to recover from failures, 1466 // so we can always consume the close. 1467 T.consumeClose(); 1468 break; 1469 case OpenACCDirectiveKind::Wait: 1470 // OpenACC has an optional paren-wrapped 'wait-argument'. 1471 WaitInfo = ParseOpenACCWaitArgument(DirLoc, /*IsDirective=*/true); 1472 if (WaitInfo.Failed) 1473 T.skipToEnd(); 1474 else 1475 T.consumeClose(); 1476 break; 1477 } 1478 } else if (DirKind == OpenACCDirectiveKind::Cache) { 1479 // Cache's paren var-list is required, so error here if it isn't provided. 1480 // We know that the consumeOpen above left the first non-paren here, so 1481 // diagnose, then continue as if it was completely omitted. 1482 Diag(Tok, diag::err_expected) << tok::l_paren; 1483 } 1484 1485 // Parses the list of clauses, if present, plus set up return value. 1486 OpenACCDirectiveParseInfo ParseInfo{DirKind, 1487 StartLoc, 1488 DirLoc, 1489 T.getOpenLocation(), 1490 T.getCloseLocation(), 1491 /*EndLoc=*/SourceLocation{}, 1492 WaitInfo.QueuesLoc, 1493 WaitInfo.getAllExprs(), 1494 ParseOpenACCClauseList(DirKind)}; 1495 1496 assert(Tok.is(tok::annot_pragma_openacc_end) && 1497 "Didn't parse all OpenACC Clauses"); 1498 ParseInfo.EndLoc = ConsumeAnnotationToken(); 1499 assert(ParseInfo.EndLoc.isValid() && 1500 "Terminating annotation token not present"); 1501 1502 return ParseInfo; 1503 } 1504 1505 // Parse OpenACC directive on a declaration. 1506 Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { 1507 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 1508 1509 ParsingOpenACCDirectiveRAII DirScope(*this); 1510 1511 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); 1512 1513 if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind, 1514 DirInfo.StartLoc)) 1515 return nullptr; 1516 1517 // TODO OpenACC: Do whatever decl parsing is required here. 1518 return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective()); 1519 } 1520 1521 // Parse OpenACC Directive on a Statement. 1522 StmtResult Parser::ParseOpenACCDirectiveStmt() { 1523 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 1524 1525 ParsingOpenACCDirectiveRAII DirScope(*this); 1526 1527 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); 1528 if (getActions().OpenACC().ActOnStartStmtDirective( 1529 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses)) 1530 return StmtError(); 1531 1532 StmtResult AssocStmt; 1533 if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) { 1534 SemaOpenACC::AssociatedStmtRAII AssocStmtRAII( 1535 getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {}, 1536 DirInfo.Clauses); 1537 ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false); 1538 ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind)); 1539 1540 AssocStmt = getActions().OpenACC().ActOnAssociatedStmt( 1541 DirInfo.StartLoc, DirInfo.DirKind, DirInfo.Clauses, ParseStatement()); 1542 } 1543 1544 return getActions().OpenACC().ActOnEndStmtDirective( 1545 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc, 1546 DirInfo.MiscLoc, DirInfo.Exprs, DirInfo.RParenLoc, DirInfo.EndLoc, 1547 DirInfo.Clauses, AssocStmt); 1548 } 1549