1ff219ea9SErich Keane //===--- ParseOpenACC.cpp - OpenACC-specific parsing support --------------===// 2ff219ea9SErich Keane // 3ff219ea9SErich Keane // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ff219ea9SErich Keane // See https://llvm.org/LICENSE.txt for license information. 5ff219ea9SErich Keane // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ff219ea9SErich Keane // 7ff219ea9SErich Keane //===----------------------------------------------------------------------===// 8ff219ea9SErich Keane // 9ff219ea9SErich Keane // This file implements the parsing logic for OpenACC language features. 10ff219ea9SErich Keane // 11ff219ea9SErich Keane //===----------------------------------------------------------------------===// 12ff219ea9SErich Keane 1326fee0ffSErich Keane #include "clang/AST/OpenACCClause.h" 14834dfd23SKazu Hirata #include "clang/Basic/DiagnosticParse.h" 1564b6ef02SErich Keane #include "clang/Basic/OpenACCKinds.h" 16ff219ea9SErich Keane #include "clang/Parse/Parser.h" 1764b6ef02SErich Keane #include "clang/Parse/RAIIObjectsForParser.h" 18e45f6e56SVlad Serebrennikov #include "clang/Sema/SemaOpenACC.h" 1964b6ef02SErich Keane #include "llvm/ADT/StringRef.h" 2064b6ef02SErich Keane #include "llvm/ADT/StringSwitch.h" 21ff219ea9SErich Keane 22ff219ea9SErich Keane using namespace clang; 2364b6ef02SErich Keane using namespace llvm; 24ff219ea9SErich Keane 2564b6ef02SErich Keane namespace { 26147b38b1SErich Keane // An enum that contains the extended 'partial' parsed variants. This type 27147b38b1SErich Keane // should never escape the initial parse functionality, but is useful for 28147b38b1SErich Keane // simplifying the implementation. 29147b38b1SErich Keane enum class OpenACCDirectiveKindEx { 30147b38b1SErich Keane Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid), 31147b38b1SErich Keane // 'enter data' and 'exit data' 32147b38b1SErich Keane Enter, 33147b38b1SErich Keane Exit, 34147b38b1SErich Keane }; 3564b6ef02SErich Keane 36147b38b1SErich Keane // Translate single-token string representations to the OpenACC Directive Kind. 37147b38b1SErich Keane // This doesn't completely comprehend 'Compound Constructs' (as it just 38147b38b1SErich Keane // identifies the first token), and doesn't fully handle 'enter data', 'exit 39147b38b1SErich Keane // data', nor any of the 'atomic' variants, just the first token of each. So 40147b38b1SErich Keane // this should only be used by `ParseOpenACCDirectiveKind`. 4126f8e146Serichkeane OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { 4226f8e146Serichkeane if (!Tok.is(tok::identifier)) 4326f8e146Serichkeane return OpenACCDirectiveKindEx::Invalid; 44147b38b1SErich Keane OpenACCDirectiveKind DirKind = 4526f8e146Serichkeane llvm::StringSwitch<OpenACCDirectiveKind>( 4626f8e146Serichkeane Tok.getIdentifierInfo()->getName()) 4764b6ef02SErich Keane .Case("parallel", OpenACCDirectiveKind::Parallel) 489bd5f808Serichkeane .Case("serial", OpenACCDirectiveKind::Serial) 499bd5f808Serichkeane .Case("kernels", OpenACCDirectiveKind::Kernels) 509bd5f808Serichkeane .Case("data", OpenACCDirectiveKind::Data) 519bd5f808Serichkeane .Case("host_data", OpenACCDirectiveKind::HostData) 529bd5f808Serichkeane .Case("loop", OpenACCDirectiveKind::Loop) 53721558aeSErich Keane .Case("cache", OpenACCDirectiveKind::Cache) 5404e9b61cSErich Keane .Case("atomic", OpenACCDirectiveKind::Atomic) 55ba1c869fSErich Keane .Case("routine", OpenACCDirectiveKind::Routine) 569bd5f808Serichkeane .Case("declare", OpenACCDirectiveKind::Declare) 579bd5f808Serichkeane .Case("init", OpenACCDirectiveKind::Init) 589bd5f808Serichkeane .Case("shutdown", OpenACCDirectiveKind::Shutdown) 59b14731feSerichkeane .Case("set", OpenACCDirectiveKind::Set) 609bd5f808Serichkeane .Case("update", OpenACCDirectiveKind::Update) 61df3db035SErich Keane .Case("wait", OpenACCDirectiveKind::Wait) 6264b6ef02SErich Keane .Default(OpenACCDirectiveKind::Invalid); 63147b38b1SErich Keane 64147b38b1SErich Keane if (DirKind != OpenACCDirectiveKind::Invalid) 65147b38b1SErich Keane return static_cast<OpenACCDirectiveKindEx>(DirKind); 66147b38b1SErich Keane 6726f8e146Serichkeane return llvm::StringSwitch<OpenACCDirectiveKindEx>( 6826f8e146Serichkeane Tok.getIdentifierInfo()->getName()) 69147b38b1SErich Keane .Case("enter", OpenACCDirectiveKindEx::Enter) 70147b38b1SErich Keane .Case("exit", OpenACCDirectiveKindEx::Exit) 71147b38b1SErich Keane .Default(OpenACCDirectiveKindEx::Invalid); 7264b6ef02SErich Keane } 7364b6ef02SErich Keane 74fdee0a35SErich Keane // Translate single-token string representations to the OpenCC Clause Kind. 75fdee0a35SErich Keane OpenACCClauseKind getOpenACCClauseKind(Token Tok) { 76fdee0a35SErich Keane // auto is a keyword in some language modes, so make sure we parse it 77fdee0a35SErich Keane // correctly. 78fdee0a35SErich Keane if (Tok.is(tok::kw_auto)) 79fdee0a35SErich Keane return OpenACCClauseKind::Auto; 80fdee0a35SErich Keane 810e8b09c4SErich Keane // default is a keyword, so make sure we parse it correctly. 820e8b09c4SErich Keane if (Tok.is(tok::kw_default)) 830e8b09c4SErich Keane return OpenACCClauseKind::Default; 840e8b09c4SErich Keane 85e6b7c8c4Serichkeane // if is also a keyword, make sure we parse it correctly. 86e6b7c8c4Serichkeane if (Tok.is(tok::kw_if)) 87e6b7c8c4Serichkeane return OpenACCClauseKind::If; 88e6b7c8c4Serichkeane 89ee090cb8Serichkeane // 'private' is also a keyword, make sure we parse it correctly. 90fa67986dSErich Keane if (Tok.is(tok::kw_private)) 91fa67986dSErich Keane return OpenACCClauseKind::Private; 92fa67986dSErich Keane 93ee090cb8Serichkeane // 'delete' is a keyword, make sure we parse it correctly. 94ee090cb8Serichkeane if (Tok.is(tok::kw_delete)) 95ee090cb8Serichkeane return OpenACCClauseKind::Delete; 96ee090cb8Serichkeane 97fdee0a35SErich Keane if (!Tok.is(tok::identifier)) 98fdee0a35SErich Keane return OpenACCClauseKind::Invalid; 99fdee0a35SErich Keane 100fdee0a35SErich Keane return llvm::StringSwitch<OpenACCClauseKind>( 101fdee0a35SErich Keane Tok.getIdentifierInfo()->getName()) 10262a384caSerichkeane .Case("async", OpenACCClauseKind::Async) 1037700ea10Serichkeane .Case("attach", OpenACCClauseKind::Attach) 104fdee0a35SErich Keane .Case("auto", OpenACCClauseKind::Auto) 10558b77b85Serichkeane .Case("bind", OpenACCClauseKind::Bind) 1067b8f7f75Serichkeane .Case("create", OpenACCClauseKind::Create) 10701e91a2dSerichkeane .Case("pcreate", OpenACCClauseKind::PCreate) 10801e91a2dSerichkeane .Case("present_or_create", OpenACCClauseKind::PresentOrCreate) 1093a82a1c3Serichkeane .Case("collapse", OpenACCClauseKind::Collapse) 110923f0392Serichkeane .Case("copy", OpenACCClauseKind::Copy) 111054f7c05Serichkeane .Case("pcopy", OpenACCClauseKind::PCopy) 112054f7c05Serichkeane .Case("present_or_copy", OpenACCClauseKind::PresentOrCopy) 1137b8f7f75Serichkeane .Case("copyin", OpenACCClauseKind::CopyIn) 11401e91a2dSerichkeane .Case("pcopyin", OpenACCClauseKind::PCopyIn) 11501e91a2dSerichkeane .Case("present_or_copyin", OpenACCClauseKind::PresentOrCopyIn) 116eca25bbdSerichkeane .Case("copyout", OpenACCClauseKind::CopyOut) 11701e91a2dSerichkeane .Case("pcopyout", OpenACCClauseKind::PCopyOut) 11801e91a2dSerichkeane .Case("present_or_copyout", OpenACCClauseKind::PresentOrCopyOut) 1190e8b09c4SErich Keane .Case("default", OpenACCClauseKind::Default) 12004952c5bSerichkeane .Case("default_async", OpenACCClauseKind::DefaultAsync) 1217700ea10Serichkeane .Case("delete", OpenACCClauseKind::Delete) 1227700ea10Serichkeane .Case("detach", OpenACCClauseKind::Detach) 1237700ea10Serichkeane .Case("device", OpenACCClauseKind::Device) 12404952c5bSerichkeane .Case("device_num", OpenACCClauseKind::DeviceNum) 1257700ea10Serichkeane .Case("device_resident", OpenACCClauseKind::DeviceResident) 1262531a15dSerichkeane .Case("device_type", OpenACCClauseKind::DeviceType) 1277700ea10Serichkeane .Case("deviceptr", OpenACCClauseKind::DevicePtr) 1282531a15dSerichkeane .Case("dtype", OpenACCClauseKind::DType) 129fdee0a35SErich Keane .Case("finalize", OpenACCClauseKind::Finalize) 1307700ea10Serichkeane .Case("firstprivate", OpenACCClauseKind::FirstPrivate) 131b52fe2dfSerichkeane .Case("gang", OpenACCClauseKind::Gang) 1327700ea10Serichkeane .Case("host", OpenACCClauseKind::Host) 133e6b7c8c4Serichkeane .Case("if", OpenACCClauseKind::If) 134fdee0a35SErich Keane .Case("if_present", OpenACCClauseKind::IfPresent) 135fdee0a35SErich Keane .Case("independent", OpenACCClauseKind::Independent) 1367700ea10Serichkeane .Case("link", OpenACCClauseKind::Link) 1377700ea10Serichkeane .Case("no_create", OpenACCClauseKind::NoCreate) 13804952c5bSerichkeane .Case("num_gangs", OpenACCClauseKind::NumGangs) 13904952c5bSerichkeane .Case("num_workers", OpenACCClauseKind::NumWorkers) 140fdee0a35SErich Keane .Case("nohost", OpenACCClauseKind::NoHost) 1417700ea10Serichkeane .Case("present", OpenACCClauseKind::Present) 1427700ea10Serichkeane .Case("private", OpenACCClauseKind::Private) 14339739552Serichkeane .Case("reduction", OpenACCClauseKind::Reduction) 14487f67c25Serichkeane .Case("self", OpenACCClauseKind::Self) 145fdee0a35SErich Keane .Case("seq", OpenACCClauseKind::Seq) 146463529f3Serichkeane .Case("tile", OpenACCClauseKind::Tile) 147dd5ce457Serichkeane .Case("use_device", OpenACCClauseKind::UseDevice) 148fdee0a35SErich Keane .Case("vector", OpenACCClauseKind::Vector) 1490d8e333aSerichkeane .Case("vector_length", OpenACCClauseKind::VectorLength) 1500dd0cbd3Serichkeane .Case("wait", OpenACCClauseKind::Wait) 151fdee0a35SErich Keane .Case("worker", OpenACCClauseKind::Worker) 152fdee0a35SErich Keane .Default(OpenACCClauseKind::Invalid); 153fdee0a35SErich Keane } 154fdee0a35SErich Keane 15504e9b61cSErich Keane // Since 'atomic' is effectively a compound directive, this will decode the 15604e9b61cSErich Keane // second part of the directive. 15726f8e146Serichkeane OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { 15826f8e146Serichkeane if (!Tok.is(tok::identifier)) 15926f8e146Serichkeane return OpenACCAtomicKind::Invalid; 16026f8e146Serichkeane return llvm::StringSwitch<OpenACCAtomicKind>( 16126f8e146Serichkeane Tok.getIdentifierInfo()->getName()) 16204e9b61cSErich Keane .Case("read", OpenACCAtomicKind::Read) 16304e9b61cSErich Keane .Case("write", OpenACCAtomicKind::Write) 16404e9b61cSErich Keane .Case("update", OpenACCAtomicKind::Update) 16504e9b61cSErich Keane .Case("capture", OpenACCAtomicKind::Capture) 16604e9b61cSErich Keane .Default(OpenACCAtomicKind::Invalid); 16704e9b61cSErich Keane } 16804e9b61cSErich Keane 1690e8b09c4SErich Keane OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) { 1700e8b09c4SErich Keane if (!Tok.is(tok::identifier)) 1710e8b09c4SErich Keane return OpenACCDefaultClauseKind::Invalid; 1720e8b09c4SErich Keane 1730e8b09c4SErich Keane return llvm::StringSwitch<OpenACCDefaultClauseKind>( 1740e8b09c4SErich Keane Tok.getIdentifierInfo()->getName()) 1750e8b09c4SErich Keane .Case("none", OpenACCDefaultClauseKind::None) 1760e8b09c4SErich Keane .Case("present", OpenACCDefaultClauseKind::Present) 1770e8b09c4SErich Keane .Default(OpenACCDefaultClauseKind::Invalid); 1780e8b09c4SErich Keane } 1790e8b09c4SErich Keane 180df3db035SErich Keane enum class OpenACCSpecialTokenKind { 1819b154dadSerichkeane ReadOnly, 182df3db035SErich Keane DevNum, 183df3db035SErich Keane Queues, 184eca25bbdSerichkeane Zero, 1853a82a1c3Serichkeane Force, 1860dd72eb2Serichkeane Num, 1870dd72eb2Serichkeane Length, 188b52fe2dfSerichkeane Dim, 189b52fe2dfSerichkeane Static, 190df3db035SErich Keane }; 191df3db035SErich Keane 192df3db035SErich Keane bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { 193b52fe2dfSerichkeane if (Tok.is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static) 194b52fe2dfSerichkeane return true; 195b52fe2dfSerichkeane 196df3db035SErich Keane if (!Tok.is(tok::identifier)) 197df3db035SErich Keane return false; 198df3db035SErich Keane 199df3db035SErich Keane switch (Kind) { 2009b154dadSerichkeane case OpenACCSpecialTokenKind::ReadOnly: 2019b154dadSerichkeane return Tok.getIdentifierInfo()->isStr("readonly"); 202df3db035SErich Keane case OpenACCSpecialTokenKind::DevNum: 203df3db035SErich Keane return Tok.getIdentifierInfo()->isStr("devnum"); 204df3db035SErich Keane case OpenACCSpecialTokenKind::Queues: 205df3db035SErich Keane return Tok.getIdentifierInfo()->isStr("queues"); 206eca25bbdSerichkeane case OpenACCSpecialTokenKind::Zero: 207eca25bbdSerichkeane return Tok.getIdentifierInfo()->isStr("zero"); 2083a82a1c3Serichkeane case OpenACCSpecialTokenKind::Force: 2093a82a1c3Serichkeane return Tok.getIdentifierInfo()->isStr("force"); 2100dd72eb2Serichkeane case OpenACCSpecialTokenKind::Num: 2110dd72eb2Serichkeane return Tok.getIdentifierInfo()->isStr("num"); 2120dd72eb2Serichkeane case OpenACCSpecialTokenKind::Length: 2130dd72eb2Serichkeane return Tok.getIdentifierInfo()->isStr("length"); 214b52fe2dfSerichkeane case OpenACCSpecialTokenKind::Dim: 215b52fe2dfSerichkeane return Tok.getIdentifierInfo()->isStr("dim"); 216b52fe2dfSerichkeane case OpenACCSpecialTokenKind::Static: 217b52fe2dfSerichkeane return Tok.getIdentifierInfo()->isStr("static"); 218df3db035SErich Keane } 219df3db035SErich Keane llvm_unreachable("Unknown 'Kind' Passed"); 220df3db035SErich Keane } 221df3db035SErich Keane 2229e068cd7SErich Keane /// Used for cases where we have a token we want to check against an 2239e068cd7SErich Keane /// 'identifier-like' token, but don't want to give awkward error messages in 2249e068cd7SErich Keane /// cases where it is accidentially a keyword. 2259e068cd7SErich Keane bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) { 2269e068cd7SErich Keane if (Tok.is(tok::identifier)) 2279e068cd7SErich Keane return true; 2289e068cd7SErich Keane 2299e068cd7SErich Keane if (!Tok.isAnnotation() && Tok.getIdentifierInfo() && 2309e068cd7SErich Keane Tok.getIdentifierInfo()->isKeyword(P.getLangOpts())) 2319e068cd7SErich Keane return true; 2329e068cd7SErich Keane 2339e068cd7SErich Keane return false; 2349e068cd7SErich Keane } 2359e068cd7SErich Keane 2369e068cd7SErich Keane /// Parses and consumes an identifer followed immediately by a single colon, and 2379e068cd7SErich Keane /// diagnoses if it is not the 'special token' kind that we require. Used when 2389e068cd7SErich Keane /// the tag is the only valid value. 2399e068cd7SErich Keane /// Return 'true' if the special token was matched, false if no special token, 2409e068cd7SErich Keane /// or an invalid special token was found. 2419e068cd7SErich Keane template <typename DirOrClauseTy> 242d5000e9cSerichkeane bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind, 2439e068cd7SErich Keane DirOrClauseTy DirOrClause) { 2449e068cd7SErich Keane Token IdentTok = P.getCurToken(); 2459e068cd7SErich Keane // If this is an identifier-like thing followed by ':', it is one of the 2469e068cd7SErich Keane // OpenACC 'special' name tags, so consume it. 2479e068cd7SErich Keane if (isTokenIdentifierOrKeyword(P, IdentTok) && P.NextToken().is(tok::colon)) { 2489e068cd7SErich Keane P.ConsumeToken(); 2499e068cd7SErich Keane P.ConsumeToken(); 2509e068cd7SErich Keane 2519e068cd7SErich Keane if (!isOpenACCSpecialToken(Kind, IdentTok)) { 2529e068cd7SErich Keane P.Diag(IdentTok, diag::err_acc_invalid_tag_kind) 2539e068cd7SErich Keane << IdentTok.getIdentifierInfo() << DirOrClause 2549e068cd7SErich Keane << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>; 2559e068cd7SErich Keane return false; 2569e068cd7SErich Keane } 2579e068cd7SErich Keane 2589e068cd7SErich Keane return true; 2599e068cd7SErich Keane } 2609e068cd7SErich Keane 2619e068cd7SErich Keane return false; 2629e068cd7SErich Keane } 2639e068cd7SErich Keane 26426f8e146Serichkeane bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { 26526f8e146Serichkeane if (!Tok.is(tok::identifier)) 26626f8e146Serichkeane return false; 26726f8e146Serichkeane 26870f41022SErich Keane switch (Kind) { 26970f41022SErich Keane case OpenACCDirectiveKind::Parallel: 27026f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("parallel"); 27170f41022SErich Keane case OpenACCDirectiveKind::Serial: 27226f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("serial"); 27370f41022SErich Keane case OpenACCDirectiveKind::Kernels: 27426f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("kernels"); 27570f41022SErich Keane case OpenACCDirectiveKind::Data: 27626f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("data"); 27770f41022SErich Keane case OpenACCDirectiveKind::HostData: 27826f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("host_data"); 27970f41022SErich Keane case OpenACCDirectiveKind::Loop: 28026f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("loop"); 281721558aeSErich Keane case OpenACCDirectiveKind::Cache: 28226f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("cache"); 28370f41022SErich Keane 28470f41022SErich Keane case OpenACCDirectiveKind::ParallelLoop: 28570f41022SErich Keane case OpenACCDirectiveKind::SerialLoop: 28670f41022SErich Keane case OpenACCDirectiveKind::KernelsLoop: 287147b38b1SErich Keane case OpenACCDirectiveKind::EnterData: 288147b38b1SErich Keane case OpenACCDirectiveKind::ExitData: 28970f41022SErich Keane return false; 29070f41022SErich Keane 29104e9b61cSErich Keane case OpenACCDirectiveKind::Atomic: 29226f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("atomic"); 293ba1c869fSErich Keane case OpenACCDirectiveKind::Routine: 29426f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("routine"); 29570f41022SErich Keane case OpenACCDirectiveKind::Declare: 29626f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("declare"); 29770f41022SErich Keane case OpenACCDirectiveKind::Init: 29826f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("init"); 29970f41022SErich Keane case OpenACCDirectiveKind::Shutdown: 30026f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("shutdown"); 30170f41022SErich Keane case OpenACCDirectiveKind::Set: 30226f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("set"); 30370f41022SErich Keane case OpenACCDirectiveKind::Update: 30426f8e146Serichkeane return Tok.getIdentifierInfo()->isStr("update"); 305df3db035SErich Keane case OpenACCDirectiveKind::Wait: 306df3db035SErich Keane return Tok.getIdentifierInfo()->isStr("wait"); 30770f41022SErich Keane case OpenACCDirectiveKind::Invalid: 30870f41022SErich Keane return false; 30970f41022SErich Keane } 31070f41022SErich Keane llvm_unreachable("Unknown 'Kind' Passed"); 31170f41022SErich Keane } 31270f41022SErich Keane 31339739552Serichkeane OpenACCReductionOperator ParseReductionOperator(Parser &P) { 31439739552Serichkeane // If there is no colon, treat as if the reduction operator was missing, else 31539739552Serichkeane // we probably will not recover from it in the case where an expression starts 31639739552Serichkeane // with one of the operator tokens. 31739739552Serichkeane if (P.NextToken().isNot(tok::colon)) { 31839739552Serichkeane P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator); 31939739552Serichkeane return OpenACCReductionOperator::Invalid; 32039739552Serichkeane } 32139739552Serichkeane Token ReductionKindTok = P.getCurToken(); 32239739552Serichkeane // Consume both the kind and the colon. 32339739552Serichkeane P.ConsumeToken(); 32439739552Serichkeane P.ConsumeToken(); 32539739552Serichkeane 32639739552Serichkeane switch (ReductionKindTok.getKind()) { 32739739552Serichkeane case tok::plus: 32839739552Serichkeane return OpenACCReductionOperator::Addition; 32939739552Serichkeane case tok::star: 33039739552Serichkeane return OpenACCReductionOperator::Multiplication; 33139739552Serichkeane case tok::amp: 33239739552Serichkeane return OpenACCReductionOperator::BitwiseAnd; 33339739552Serichkeane case tok::pipe: 33439739552Serichkeane return OpenACCReductionOperator::BitwiseOr; 33539739552Serichkeane case tok::caret: 33639739552Serichkeane return OpenACCReductionOperator::BitwiseXOr; 33739739552Serichkeane case tok::ampamp: 33839739552Serichkeane return OpenACCReductionOperator::And; 33939739552Serichkeane case tok::pipepipe: 34039739552Serichkeane return OpenACCReductionOperator::Or; 34139739552Serichkeane case tok::identifier: 34239739552Serichkeane if (ReductionKindTok.getIdentifierInfo()->isStr("max")) 34339739552Serichkeane return OpenACCReductionOperator::Max; 34439739552Serichkeane if (ReductionKindTok.getIdentifierInfo()->isStr("min")) 34539739552Serichkeane return OpenACCReductionOperator::Min; 34676739d12SFangrui Song [[fallthrough]]; 34739739552Serichkeane default: 34839739552Serichkeane P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator); 34939739552Serichkeane return OpenACCReductionOperator::Invalid; 35039739552Serichkeane } 35139739552Serichkeane llvm_unreachable("Reduction op token kind not caught by 'default'?"); 35239739552Serichkeane } 35339739552Serichkeane 3540e8b09c4SErich Keane /// Used for cases where we expect an identifier-like token, but don't want to 3550e8b09c4SErich Keane /// give awkward error messages in cases where it is accidentially a keyword. 3560e8b09c4SErich Keane bool expectIdentifierOrKeyword(Parser &P) { 3570e8b09c4SErich Keane Token Tok = P.getCurToken(); 3580e8b09c4SErich Keane 3599e068cd7SErich Keane if (isTokenIdentifierOrKeyword(P, Tok)) 3600e8b09c4SErich Keane return false; 3610e8b09c4SErich Keane 3620e8b09c4SErich Keane P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; 3630e8b09c4SErich Keane return true; 3640e8b09c4SErich Keane } 3650e8b09c4SErich Keane 366147b38b1SErich Keane OpenACCDirectiveKind 367147b38b1SErich Keane ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, 368147b38b1SErich Keane OpenACCDirectiveKindEx ExtDirKind) { 369147b38b1SErich Keane Token SecondTok = P.getCurToken(); 370147b38b1SErich Keane 371147b38b1SErich Keane if (SecondTok.isAnnotation()) { 37226f8e146Serichkeane P.Diag(FirstTok, diag::err_acc_invalid_directive) 37326f8e146Serichkeane << 0 << FirstTok.getIdentifierInfo(); 374147b38b1SErich Keane return OpenACCDirectiveKind::Invalid; 375147b38b1SErich Keane } 376147b38b1SErich Keane 377fdee0a35SErich Keane // Consume the second name anyway, this way we can continue on without making 378fdee0a35SErich Keane // this oddly look like a clause. 379fdee0a35SErich Keane P.ConsumeAnyToken(); 380fdee0a35SErich Keane 38126f8e146Serichkeane if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { 38226f8e146Serichkeane if (!SecondTok.is(tok::identifier)) 38326f8e146Serichkeane P.Diag(SecondTok, diag::err_expected) << tok::identifier; 38426f8e146Serichkeane else 385147b38b1SErich Keane P.Diag(FirstTok, diag::err_acc_invalid_directive) 38626f8e146Serichkeane << 1 << FirstTok.getIdentifierInfo()->getName() 38726f8e146Serichkeane << SecondTok.getIdentifierInfo()->getName(); 388147b38b1SErich Keane return OpenACCDirectiveKind::Invalid; 389147b38b1SErich Keane } 390147b38b1SErich Keane 391147b38b1SErich Keane return ExtDirKind == OpenACCDirectiveKindEx::Enter 392147b38b1SErich Keane ? OpenACCDirectiveKind::EnterData 393147b38b1SErich Keane : OpenACCDirectiveKind::ExitData; 394147b38b1SErich Keane } 395147b38b1SErich Keane 39604e9b61cSErich Keane OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) { 39704e9b61cSErich Keane Token AtomicClauseToken = P.getCurToken(); 39804e9b61cSErich Keane 39904e9b61cSErich Keane // #pragma acc atomic is equivilent to update: 40004e9b61cSErich Keane if (AtomicClauseToken.isAnnotation()) 40104e9b61cSErich Keane return OpenACCAtomicKind::Update; 40204e9b61cSErich Keane 40326f8e146Serichkeane OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken); 40404e9b61cSErich Keane 40504e9b61cSErich Keane // If we don't know what this is, treat it as 'nothing', and treat the rest of 40604e9b61cSErich Keane // this as a clause list, which, despite being invalid, is likely what the 40704e9b61cSErich Keane // user was trying to do. 40804e9b61cSErich Keane if (AtomicKind == OpenACCAtomicKind::Invalid) 40904e9b61cSErich Keane return OpenACCAtomicKind::Update; 41004e9b61cSErich Keane 41104e9b61cSErich Keane P.ConsumeToken(); 41204e9b61cSErich Keane return AtomicKind; 41304e9b61cSErich Keane } 41404e9b61cSErich Keane 41564b6ef02SErich Keane // Parse and consume the tokens for OpenACC Directive/Construct kinds. 41664b6ef02SErich Keane OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { 41764b6ef02SErich Keane Token FirstTok = P.getCurToken(); 41861683376Serichkeane 41961683376Serichkeane // Just #pragma acc can get us immediately to the end, make sure we don't 42061683376Serichkeane // introspect on the spelling before then. 421731361cdSerichkeane if (FirstTok.isNot(tok::identifier)) { 42261683376Serichkeane P.Diag(FirstTok, diag::err_acc_missing_directive); 423fdee0a35SErich Keane 424fdee0a35SErich Keane if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 425fdee0a35SErich Keane P.ConsumeAnyToken(); 426fdee0a35SErich Keane 42761683376Serichkeane return OpenACCDirectiveKind::Invalid; 42861683376Serichkeane } 42961683376Serichkeane 43064b6ef02SErich Keane P.ConsumeToken(); 43164b6ef02SErich Keane 43226f8e146Serichkeane OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok); 43364b6ef02SErich Keane 434147b38b1SErich Keane // OpenACCDirectiveKindEx is meant to be an extended list 435147b38b1SErich Keane // over OpenACCDirectiveKind, so any value below Invalid is one of the 436147b38b1SErich Keane // OpenACCDirectiveKind values. This switch takes care of all of the extra 437147b38b1SErich Keane // parsing required for the Extended values. At the end of this block, 438147b38b1SErich Keane // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can 439147b38b1SErich Keane // immediately cast it and use it as that. 440147b38b1SErich Keane if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) { 441147b38b1SErich Keane switch (ExDirKind) { 44226f8e146Serichkeane case OpenACCDirectiveKindEx::Invalid: { 443147b38b1SErich Keane P.Diag(FirstTok, diag::err_acc_invalid_directive) 44426f8e146Serichkeane << 0 << FirstTok.getIdentifierInfo(); 445147b38b1SErich Keane return OpenACCDirectiveKind::Invalid; 44626f8e146Serichkeane } 447147b38b1SErich Keane case OpenACCDirectiveKindEx::Enter: 448147b38b1SErich Keane case OpenACCDirectiveKindEx::Exit: 44926f8e146Serichkeane return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind); 450147b38b1SErich Keane } 451147b38b1SErich Keane } 452147b38b1SErich Keane 453147b38b1SErich Keane OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind); 45464b6ef02SErich Keane 45570f41022SErich Keane // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any 45670f41022SErich Keane // other attempt at a combined construct will be diagnosed as an invalid 45770f41022SErich Keane // clause. 45870f41022SErich Keane Token SecondTok = P.getCurToken(); 45970f41022SErich Keane if (!SecondTok.isAnnotation() && 46026f8e146Serichkeane isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) { 46170f41022SErich Keane switch (DirKind) { 46270f41022SErich Keane default: 46370f41022SErich Keane // Nothing to do except in the below cases, as they should be diagnosed as 46470f41022SErich Keane // a clause. 46570f41022SErich Keane break; 46670f41022SErich Keane case OpenACCDirectiveKind::Parallel: 46770f41022SErich Keane P.ConsumeToken(); 46870f41022SErich Keane return OpenACCDirectiveKind::ParallelLoop; 46970f41022SErich Keane case OpenACCDirectiveKind::Serial: 47070f41022SErich Keane P.ConsumeToken(); 47170f41022SErich Keane return OpenACCDirectiveKind::SerialLoop; 47270f41022SErich Keane case OpenACCDirectiveKind::Kernels: 47370f41022SErich Keane P.ConsumeToken(); 47470f41022SErich Keane return OpenACCDirectiveKind::KernelsLoop; 47570f41022SErich Keane } 47670f41022SErich Keane } 47770f41022SErich Keane 47864b6ef02SErich Keane return DirKind; 47964b6ef02SErich Keane } 48064b6ef02SErich Keane 4817700ea10Serichkeane enum ClauseParensKind { 4827700ea10Serichkeane None, 4837700ea10Serichkeane Optional, 4847700ea10Serichkeane Required 4857700ea10Serichkeane }; 4867700ea10Serichkeane 4879c4e7a15Serichkeane ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind, 4889c4e7a15Serichkeane OpenACCClauseKind Kind) { 4897700ea10Serichkeane switch (Kind) { 4907700ea10Serichkeane case OpenACCClauseKind::Self: 4919c4e7a15Serichkeane return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required 4929c4e7a15Serichkeane : ClauseParensKind::Optional; 49362a384caSerichkeane case OpenACCClauseKind::Async: 4940dd72eb2Serichkeane case OpenACCClauseKind::Worker: 4950dd72eb2Serichkeane case OpenACCClauseKind::Vector: 496b52fe2dfSerichkeane case OpenACCClauseKind::Gang: 4970dd0cbd3Serichkeane case OpenACCClauseKind::Wait: 4980dd72eb2Serichkeane return ClauseParensKind::Optional; 4997700ea10Serichkeane 5007700ea10Serichkeane case OpenACCClauseKind::Default: 5017700ea10Serichkeane case OpenACCClauseKind::If: 5027b8f7f75Serichkeane case OpenACCClauseKind::Create: 50301e91a2dSerichkeane case OpenACCClauseKind::PCreate: 50401e91a2dSerichkeane case OpenACCClauseKind::PresentOrCreate: 5057700ea10Serichkeane case OpenACCClauseKind::Copy: 506054f7c05Serichkeane case OpenACCClauseKind::PCopy: 507054f7c05Serichkeane case OpenACCClauseKind::PresentOrCopy: 5087b8f7f75Serichkeane case OpenACCClauseKind::CopyIn: 50901e91a2dSerichkeane case OpenACCClauseKind::PCopyIn: 51001e91a2dSerichkeane case OpenACCClauseKind::PresentOrCopyIn: 511eca25bbdSerichkeane case OpenACCClauseKind::CopyOut: 51201e91a2dSerichkeane case OpenACCClauseKind::PCopyOut: 51301e91a2dSerichkeane case OpenACCClauseKind::PresentOrCopyOut: 5147700ea10Serichkeane case OpenACCClauseKind::UseDevice: 5157700ea10Serichkeane case OpenACCClauseKind::NoCreate: 5167700ea10Serichkeane case OpenACCClauseKind::Present: 5177700ea10Serichkeane case OpenACCClauseKind::DevicePtr: 5187700ea10Serichkeane case OpenACCClauseKind::Attach: 5197700ea10Serichkeane case OpenACCClauseKind::Detach: 5207700ea10Serichkeane case OpenACCClauseKind::Private: 5217700ea10Serichkeane case OpenACCClauseKind::FirstPrivate: 5227700ea10Serichkeane case OpenACCClauseKind::Delete: 5237700ea10Serichkeane case OpenACCClauseKind::DeviceResident: 5247700ea10Serichkeane case OpenACCClauseKind::Device: 5257700ea10Serichkeane case OpenACCClauseKind::Link: 5267700ea10Serichkeane case OpenACCClauseKind::Host: 52739739552Serichkeane case OpenACCClauseKind::Reduction: 5283a82a1c3Serichkeane case OpenACCClauseKind::Collapse: 52958b77b85Serichkeane case OpenACCClauseKind::Bind: 5300d8e333aSerichkeane case OpenACCClauseKind::VectorLength: 53104952c5bSerichkeane case OpenACCClauseKind::NumGangs: 53204952c5bSerichkeane case OpenACCClauseKind::NumWorkers: 53304952c5bSerichkeane case OpenACCClauseKind::DeviceNum: 53404952c5bSerichkeane case OpenACCClauseKind::DefaultAsync: 5352531a15dSerichkeane case OpenACCClauseKind::DeviceType: 5362531a15dSerichkeane case OpenACCClauseKind::DType: 537463529f3Serichkeane case OpenACCClauseKind::Tile: 5387700ea10Serichkeane return ClauseParensKind::Required; 5397700ea10Serichkeane 5407700ea10Serichkeane case OpenACCClauseKind::Auto: 5417700ea10Serichkeane case OpenACCClauseKind::Finalize: 5427700ea10Serichkeane case OpenACCClauseKind::IfPresent: 5437700ea10Serichkeane case OpenACCClauseKind::Independent: 5447700ea10Serichkeane case OpenACCClauseKind::Invalid: 5457700ea10Serichkeane case OpenACCClauseKind::NoHost: 5467700ea10Serichkeane case OpenACCClauseKind::Seq: 5477700ea10Serichkeane return ClauseParensKind::None; 5487700ea10Serichkeane } 5497700ea10Serichkeane llvm_unreachable("Unhandled clause kind"); 5507700ea10Serichkeane } 5517700ea10Serichkeane 5529c4e7a15Serichkeane bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind, 5539c4e7a15Serichkeane OpenACCClauseKind Kind) { 5549c4e7a15Serichkeane return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional; 55587f67c25Serichkeane } 55687f67c25Serichkeane 5579c4e7a15Serichkeane bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind, 5589c4e7a15Serichkeane OpenACCClauseKind Kind) { 5599c4e7a15Serichkeane return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required; 5600e8b09c4SErich Keane } 5610e8b09c4SErich Keane 562923f0392Serichkeane // Skip until we see the end of pragma token, but don't consume it. This is us 563923f0392Serichkeane // just giving up on the rest of the pragma so we can continue executing. We 564923f0392Serichkeane // have to do this because 'SkipUntil' considers paren balancing, which isn't 565923f0392Serichkeane // what we want. 566923f0392Serichkeane void SkipUntilEndOfDirective(Parser &P) { 567923f0392Serichkeane while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 568923f0392Serichkeane P.ConsumeAnyToken(); 569923f0392Serichkeane } 570923f0392Serichkeane 57124144d72SErich Keane bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) { 572cb891127SErich Keane switch (DirKind) { 573cb891127SErich Keane default: 574010d0115Serichkeane case OpenACCDirectiveKind::EnterData: 575010d0115Serichkeane case OpenACCDirectiveKind::ExitData: 576e34cc7c9Serichkeane case OpenACCDirectiveKind::Wait: 5774bbdb018Serichkeane case OpenACCDirectiveKind::Init: 5784bbdb018Serichkeane case OpenACCDirectiveKind::Shutdown: 57924144d72SErich Keane return false; 580cb891127SErich Keane case OpenACCDirectiveKind::Parallel: 581bb97c992Serichkeane case OpenACCDirectiveKind::Serial: 582bb97c992Serichkeane case OpenACCDirectiveKind::Kernels: 58339351f8eSerichkeane case OpenACCDirectiveKind::ParallelLoop: 58439351f8eSerichkeane case OpenACCDirectiveKind::SerialLoop: 58539351f8eSerichkeane case OpenACCDirectiveKind::KernelsLoop: 58642f4e505SErich Keane case OpenACCDirectiveKind::Loop: 587010d0115Serichkeane case OpenACCDirectiveKind::Data: 588010d0115Serichkeane case OpenACCDirectiveKind::HostData: 589cb891127SErich Keane return true; 590cb891127SErich Keane } 591cb891127SErich Keane llvm_unreachable("Unhandled directive->assoc stmt"); 59224144d72SErich Keane } 59324144d72SErich Keane 59426cc6f12SErich Keane unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) { 59526cc6f12SErich Keane switch (DirKind) { 59626cc6f12SErich Keane case OpenACCDirectiveKind::Parallel: 597bb97c992Serichkeane case OpenACCDirectiveKind::Serial: 598bb97c992Serichkeane case OpenACCDirectiveKind::Kernels: 59939351f8eSerichkeane case OpenACCDirectiveKind::ParallelLoop: 60039351f8eSerichkeane case OpenACCDirectiveKind::SerialLoop: 60139351f8eSerichkeane case OpenACCDirectiveKind::KernelsLoop: 60226cc6f12SErich Keane // Mark this as a BreakScope/ContinueScope as well as a compute construct 60326cc6f12SErich Keane // so that we can diagnose trying to 'break'/'continue' inside of one. 60426cc6f12SErich Keane return Scope::BreakScope | Scope::ContinueScope | 60526cc6f12SErich Keane Scope::OpenACCComputeConstructScope; 606010d0115Serichkeane case OpenACCDirectiveKind::Data: 607010d0115Serichkeane case OpenACCDirectiveKind::EnterData: 608010d0115Serichkeane case OpenACCDirectiveKind::ExitData: 609010d0115Serichkeane case OpenACCDirectiveKind::HostData: 610e34cc7c9Serichkeane case OpenACCDirectiveKind::Wait: 6114bbdb018Serichkeane case OpenACCDirectiveKind::Init: 6124bbdb018Serichkeane case OpenACCDirectiveKind::Shutdown: 613010d0115Serichkeane return 0; 61426cc6f12SErich Keane case OpenACCDirectiveKind::Invalid: 61526cc6f12SErich Keane llvm_unreachable("Shouldn't be creating a scope for an invalid construct"); 61626cc6f12SErich Keane default: 61726cc6f12SErich Keane break; 61826cc6f12SErich Keane } 61926cc6f12SErich Keane return 0; 62026cc6f12SErich Keane } 62126cc6f12SErich Keane 622923f0392Serichkeane } // namespace 623923f0392Serichkeane 62426fee0ffSErich Keane Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() { 62526fee0ffSErich Keane return {nullptr, OpenACCParseCanContinue::Can}; 62626fee0ffSErich Keane } 62726fee0ffSErich Keane 62826fee0ffSErich Keane Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() { 62926fee0ffSErich Keane return {nullptr, OpenACCParseCanContinue::Cannot}; 63026fee0ffSErich Keane } 63126fee0ffSErich Keane 63226fee0ffSErich Keane Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) { 63326fee0ffSErich Keane return {Clause, OpenACCParseCanContinue::Can}; 63426fee0ffSErich Keane } 63526fee0ffSErich Keane 636daa88364SErich Keane ExprResult Parser::ParseOpenACCConditionExpr() { 637daa88364SErich Keane // FIXME: It isn't clear if the spec saying 'condition' means the same as 638daa88364SErich Keane // it does in an if/while/etc (See ParseCXXCondition), however as it was 639daa88364SErich Keane // written with Fortran/C in mind, we're going to assume it just means an 640daa88364SErich Keane // 'expression evaluating to boolean'. 641daa88364SErich Keane ExprResult ER = getActions().CorrectDelayedTyposInExpr(ParseExpression()); 642daa88364SErich Keane 643daa88364SErich Keane if (!ER.isUsable()) 644daa88364SErich Keane return ER; 645daa88364SErich Keane 646daa88364SErich Keane Sema::ConditionResult R = 647daa88364SErich Keane getActions().ActOnCondition(getCurScope(), ER.get()->getExprLoc(), 648daa88364SErich Keane ER.get(), Sema::ConditionKind::Boolean); 649daa88364SErich Keane 650daa88364SErich Keane return R.isInvalid() ? ExprError() : R.get().second; 651daa88364SErich Keane } 652daa88364SErich Keane 653923f0392Serichkeane // OpenACC 3.3, section 1.7: 654923f0392Serichkeane // To simplify the specification and convey appropriate constraint information, 655923f0392Serichkeane // a pqr-list is a comma-separated list of pdr items. The one exception is a 656923f0392Serichkeane // clause-list, which is a list of one or more clauses optionally separated by 657923f0392Serichkeane // commas. 65826fee0ffSErich Keane SmallVector<OpenACCClause *> 65926fee0ffSErich Keane Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { 66026fee0ffSErich Keane SmallVector<OpenACCClause *> Clauses; 661923f0392Serichkeane bool FirstClause = true; 662923f0392Serichkeane while (getCurToken().isNot(tok::annot_pragma_openacc_end)) { 663923f0392Serichkeane // Comma is optional in a clause-list. 664923f0392Serichkeane if (!FirstClause && getCurToken().is(tok::comma)) 665923f0392Serichkeane ConsumeToken(); 666923f0392Serichkeane FirstClause = false; 667923f0392Serichkeane 66826fee0ffSErich Keane OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind); 66926fee0ffSErich Keane if (OpenACCClause *Clause = Result.getPointer()) { 67026fee0ffSErich Keane Clauses.push_back(Clause); 67126fee0ffSErich Keane } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) { 672923f0392Serichkeane // Recovering from a bad clause is really difficult, so we just give up on 673923f0392Serichkeane // error. 674923f0392Serichkeane SkipUntilEndOfDirective(*this); 67526fee0ffSErich Keane return Clauses; 676923f0392Serichkeane } 677923f0392Serichkeane } 67826fee0ffSErich Keane return Clauses; 679923f0392Serichkeane } 680923f0392Serichkeane 681dc20a0eaSErich Keane Parser::OpenACCIntExprParseResult 682dc20a0eaSErich Keane Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, 68376600aeeSErich Keane SourceLocation Loc) { 684dc20a0eaSErich Keane ExprResult ER = ParseAssignmentExpression(); 68576600aeeSErich Keane 686dc20a0eaSErich Keane // If the actual parsing failed, we don't know the state of the parse, so 687dc20a0eaSErich Keane // don't try to continue. 68876600aeeSErich Keane if (!ER.isUsable()) 689dc20a0eaSErich Keane return {ER, OpenACCParseCanContinue::Cannot}; 69076600aeeSErich Keane 691dc20a0eaSErich Keane // Parsing can continue after the initial assignment expression parsing, so 692dc20a0eaSErich Keane // even if there was a typo, we can continue. 693dc20a0eaSErich Keane ER = getActions().CorrectDelayedTyposInExpr(ER); 694dc20a0eaSErich Keane if (!ER.isUsable()) 695dc20a0eaSErich Keane return {ER, OpenACCParseCanContinue::Can}; 696dc20a0eaSErich Keane 697dc20a0eaSErich Keane return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()), 698dc20a0eaSErich Keane OpenACCParseCanContinue::Can}; 699dc20a0eaSErich Keane } 700dc20a0eaSErich Keane 701dc20a0eaSErich Keane bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, 702dc20a0eaSErich Keane OpenACCClauseKind CK, SourceLocation Loc, 703dc20a0eaSErich Keane llvm::SmallVectorImpl<Expr *> &IntExprs) { 704dc20a0eaSErich Keane OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc); 705dc20a0eaSErich Keane 706dc20a0eaSErich Keane if (!CurResult.first.isUsable() && 707dc20a0eaSErich Keane CurResult.second == OpenACCParseCanContinue::Cannot) { 708dc20a0eaSErich Keane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 709dc20a0eaSErich Keane Parser::StopBeforeMatch); 710dc20a0eaSErich Keane return true; 711dc20a0eaSErich Keane } 712dc20a0eaSErich Keane 713dc20a0eaSErich Keane IntExprs.push_back(CurResult.first.get()); 714dc20a0eaSErich Keane 715dc20a0eaSErich Keane while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 716dc20a0eaSErich Keane ExpectAndConsume(tok::comma); 717dc20a0eaSErich Keane 718dc20a0eaSErich Keane CurResult = ParseOpenACCIntExpr(DK, CK, Loc); 719dc20a0eaSErich Keane 720dc20a0eaSErich Keane if (!CurResult.first.isUsable() && 721dc20a0eaSErich Keane CurResult.second == OpenACCParseCanContinue::Cannot) { 722dc20a0eaSErich Keane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 723dc20a0eaSErich Keane Parser::StopBeforeMatch); 724dc20a0eaSErich Keane return true; 725dc20a0eaSErich Keane } 726dc20a0eaSErich Keane IntExprs.push_back(CurResult.first.get()); 727dc20a0eaSErich Keane } 728dc20a0eaSErich Keane return false; 7290d8e333aSerichkeane } 7300d8e333aSerichkeane 7312531a15dSerichkeane /// OpenACC 3.3 Section 2.4: 7322531a15dSerichkeane /// The argument to the device_type clause is a comma-separated list of one or 7332531a15dSerichkeane /// more device architecture name identifiers, or an asterisk. 7342531a15dSerichkeane /// 7352531a15dSerichkeane /// The syntax of the device_type clause is 7362531a15dSerichkeane /// device_type( * ) 7372531a15dSerichkeane /// device_type( device-type-list ) 7382531a15dSerichkeane /// 7392531a15dSerichkeane /// The device_type clause may be abbreviated to dtype. 7408ef2011bSerichkeane bool Parser::ParseOpenACCDeviceTypeList( 7418ef2011bSerichkeane llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs) { 7422531a15dSerichkeane 7432531a15dSerichkeane if (expectIdentifierOrKeyword(*this)) { 7442531a15dSerichkeane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 7452531a15dSerichkeane Parser::StopBeforeMatch); 7468ef2011bSerichkeane return true; 7472531a15dSerichkeane } 7488ef2011bSerichkeane IdentifierInfo *Ident = getCurToken().getIdentifierInfo(); 7498ef2011bSerichkeane Archs.emplace_back(Ident, ConsumeToken()); 7502531a15dSerichkeane 7512531a15dSerichkeane while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 7522531a15dSerichkeane ExpectAndConsume(tok::comma); 7532531a15dSerichkeane 7542531a15dSerichkeane if (expectIdentifierOrKeyword(*this)) { 7552531a15dSerichkeane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 7562531a15dSerichkeane Parser::StopBeforeMatch); 7578ef2011bSerichkeane return true; 7582531a15dSerichkeane } 7598ef2011bSerichkeane Ident = getCurToken().getIdentifierInfo(); 7608ef2011bSerichkeane Archs.emplace_back(Ident, ConsumeToken()); 7612531a15dSerichkeane } 7622531a15dSerichkeane return false; 7632531a15dSerichkeane } 7642531a15dSerichkeane 765463529f3Serichkeane /// OpenACC 3.3 Section 2.9: 766463529f3Serichkeane /// size-expr is one of: 767463529f3Serichkeane // * 768463529f3Serichkeane // int-expr 769463529f3Serichkeane // Note that this is specified under 'gang-arg-list', but also applies to 'tile' 770463529f3Serichkeane // via reference. 771d412cea8SErich Keane ExprResult Parser::ParseOpenACCSizeExpr(OpenACCClauseKind CK) { 772463529f3Serichkeane // The size-expr ends up being ambiguous when only looking at the current 773463529f3Serichkeane // token, as it could be a deref of a variable/expression. 774463529f3Serichkeane if (getCurToken().is(tok::star) && 775b52fe2dfSerichkeane NextToken().isOneOf(tok::comma, tok::r_paren, 776b52fe2dfSerichkeane tok::annot_pragma_openacc_end)) { 777d412cea8SErich Keane SourceLocation AsteriskLoc = ConsumeToken(); 778d412cea8SErich Keane return getActions().OpenACC().ActOnOpenACCAsteriskSizeExpr(AsteriskLoc); 779463529f3Serichkeane } 780463529f3Serichkeane 781d412cea8SErich Keane ExprResult SizeExpr = 782d412cea8SErich Keane getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 783d412cea8SErich Keane 784d412cea8SErich Keane if (!SizeExpr.isUsable()) 785d412cea8SErich Keane return SizeExpr; 786d412cea8SErich Keane 787d412cea8SErich Keane SizeExpr = getActions().OpenACC().ActOnIntExpr( 788d412cea8SErich Keane OpenACCDirectiveKind::Invalid, CK, SizeExpr.get()->getBeginLoc(), 789d412cea8SErich Keane SizeExpr.get()); 790d412cea8SErich Keane 791d412cea8SErich Keane return SizeExpr; 792463529f3Serichkeane } 793463529f3Serichkeane 794d412cea8SErich Keane bool Parser::ParseOpenACCSizeExprList( 795d412cea8SErich Keane OpenACCClauseKind CK, llvm::SmallVectorImpl<Expr *> &SizeExprs) { 796d412cea8SErich Keane ExprResult SizeExpr = ParseOpenACCSizeExpr(CK); 797d412cea8SErich Keane if (!SizeExpr.isUsable()) { 798463529f3Serichkeane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 799463529f3Serichkeane Parser::StopBeforeMatch); 800d412cea8SErich Keane return true; 801463529f3Serichkeane } 802463529f3Serichkeane 803d412cea8SErich Keane SizeExprs.push_back(SizeExpr.get()); 804d412cea8SErich Keane 805463529f3Serichkeane while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 806463529f3Serichkeane ExpectAndConsume(tok::comma); 807463529f3Serichkeane 808d412cea8SErich Keane SizeExpr = ParseOpenACCSizeExpr(CK); 809d412cea8SErich Keane if (!SizeExpr.isUsable()) { 810463529f3Serichkeane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 811463529f3Serichkeane Parser::StopBeforeMatch); 812d412cea8SErich Keane return true; 813463529f3Serichkeane } 814d412cea8SErich Keane SizeExprs.push_back(SizeExpr.get()); 815463529f3Serichkeane } 816463529f3Serichkeane return false; 817463529f3Serichkeane } 818463529f3Serichkeane 819b52fe2dfSerichkeane /// OpenACC 3.3 Section 2.9: 820b52fe2dfSerichkeane /// 821b52fe2dfSerichkeane /// where gang-arg is one of: 822b52fe2dfSerichkeane /// [num:]int-expr 823b52fe2dfSerichkeane /// dim:int-expr 824b52fe2dfSerichkeane /// static:size-expr 8255b25c313SErich Keane Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { 826b52fe2dfSerichkeane 827b52fe2dfSerichkeane if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) && 828b52fe2dfSerichkeane NextToken().is(tok::colon)) { 829b52fe2dfSerichkeane // 'static' just takes a size-expr, which is an int-expr or an asterisk. 830b52fe2dfSerichkeane ConsumeToken(); 831b52fe2dfSerichkeane ConsumeToken(); 8325b25c313SErich Keane ExprResult Res = ParseOpenACCSizeExpr(OpenACCClauseKind::Gang); 8335b25c313SErich Keane return {OpenACCGangKind::Static, Res}; 834b52fe2dfSerichkeane } 835b52fe2dfSerichkeane 836b52fe2dfSerichkeane if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) && 837b52fe2dfSerichkeane NextToken().is(tok::colon)) { 838b52fe2dfSerichkeane ConsumeToken(); 839b52fe2dfSerichkeane ConsumeToken(); 8405b25c313SErich Keane // Parse this as a const-expression, and we'll check its integer-ness/value 8415b25c313SErich Keane // in CheckGangExpr. 8425b25c313SErich Keane ExprResult Res = 8435b25c313SErich Keane getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 8445b25c313SErich Keane return {OpenACCGangKind::Dim, Res}; 845b52fe2dfSerichkeane } 846b52fe2dfSerichkeane 847b52fe2dfSerichkeane if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) && 848b52fe2dfSerichkeane NextToken().is(tok::colon)) { 849b52fe2dfSerichkeane ConsumeToken(); 850b52fe2dfSerichkeane ConsumeToken(); 851b52fe2dfSerichkeane // Fallthrough to the 'int-expr' handling for when 'num' is omitted. 852b52fe2dfSerichkeane } 8535b25c313SErich Keane 854b52fe2dfSerichkeane // This is just the 'num' case where 'num' is optional. 8555b25c313SErich Keane ExprResult Res = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 85676600aeeSErich Keane OpenACCClauseKind::Gang, GangLoc) 8575b25c313SErich Keane .first; 8585b25c313SErich Keane return {OpenACCGangKind::Num, Res}; 859b52fe2dfSerichkeane } 860b52fe2dfSerichkeane 8615b25c313SErich Keane bool Parser::ParseOpenACCGangArgList( 8625b25c313SErich Keane SourceLocation GangLoc, llvm::SmallVectorImpl<OpenACCGangKind> &GKs, 8635b25c313SErich Keane llvm::SmallVectorImpl<Expr *> &IntExprs) { 8645b25c313SErich Keane 8655b25c313SErich Keane Parser::OpenACCGangArgRes Res = ParseOpenACCGangArg(GangLoc); 8665b25c313SErich Keane if (!Res.second.isUsable()) { 867b52fe2dfSerichkeane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 868b52fe2dfSerichkeane Parser::StopBeforeMatch); 8695b25c313SErich Keane return true; 870b52fe2dfSerichkeane } 871b52fe2dfSerichkeane 8725b25c313SErich Keane GKs.push_back(Res.first); 8735b25c313SErich Keane IntExprs.push_back(Res.second.get()); 8745b25c313SErich Keane 875b52fe2dfSerichkeane while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 876b52fe2dfSerichkeane ExpectAndConsume(tok::comma); 877b52fe2dfSerichkeane 8785b25c313SErich Keane Res = ParseOpenACCGangArg(GangLoc); 8795b25c313SErich Keane if (!Res.second.isUsable()) { 880b52fe2dfSerichkeane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 881b52fe2dfSerichkeane Parser::StopBeforeMatch); 8825b25c313SErich Keane return true; 883b52fe2dfSerichkeane } 8845b25c313SErich Keane 8855b25c313SErich Keane GKs.push_back(Res.first); 8865b25c313SErich Keane IntExprs.push_back(Res.second.get()); 887b52fe2dfSerichkeane } 888b52fe2dfSerichkeane return false; 889b52fe2dfSerichkeane } 890b52fe2dfSerichkeane 891923f0392Serichkeane // The OpenACC Clause List is a comma or space-delimited list of clauses (see 892923f0392Serichkeane // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't 893923f0392Serichkeane // really have its owner grammar and each individual one has its own definition. 894923f0392Serichkeane // However, they all are named with a single-identifier (or auto/default!) 895923f0392Serichkeane // token, followed in some cases by either braces or parens. 89626fee0ffSErich Keane Parser::OpenACCClauseParseResult 89726fee0ffSErich Keane Parser::ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses, 89826fee0ffSErich Keane OpenACCDirectiveKind DirKind) { 899923f0392Serichkeane // A number of clause names are actually keywords, so accept a keyword that 900923f0392Serichkeane // can be converted to a name. 901923f0392Serichkeane if (expectIdentifierOrKeyword(*this)) 90226fee0ffSErich Keane return OpenACCCannotContinue(); 903923f0392Serichkeane 904923f0392Serichkeane OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken()); 905923f0392Serichkeane 90626fee0ffSErich Keane if (Kind == OpenACCClauseKind::Invalid) { 90726fee0ffSErich Keane Diag(getCurToken(), diag::err_acc_invalid_clause) 908923f0392Serichkeane << getCurToken().getIdentifierInfo(); 90926fee0ffSErich Keane return OpenACCCannotContinue(); 91026fee0ffSErich Keane } 911923f0392Serichkeane 912923f0392Serichkeane // Consume the clause name. 91324144d72SErich Keane SourceLocation ClauseLoc = ConsumeToken(); 914923f0392Serichkeane 91526fee0ffSErich Keane return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc); 916923f0392Serichkeane } 917923f0392Serichkeane 91826fee0ffSErich Keane Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( 91926fee0ffSErich Keane ArrayRef<const OpenACCClause *> ExistingClauses, 92026fee0ffSErich Keane OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind, 92126fee0ffSErich Keane SourceLocation ClauseLoc) { 922923f0392Serichkeane BalancedDelimiterTracker Parens(*this, tok::l_paren, 9230e8b09c4SErich Keane tok::annot_pragma_openacc_end); 92426fee0ffSErich Keane SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc); 9250e8b09c4SErich Keane 92626fee0ffSErich Keane if (ClauseHasRequiredParens(DirKind, ClauseKind)) { 9270e8b09c4SErich Keane if (Parens.expectAndConsume()) { 9280e8b09c4SErich Keane // We are missing a paren, so assume that the person just forgot the 9290e8b09c4SErich Keane // parameter. Return 'false' so we try to continue on and parse the next 9300e8b09c4SErich Keane // clause. 931923f0392Serichkeane SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, 9320e8b09c4SErich Keane Parser::StopBeforeMatch); 93326fee0ffSErich Keane return OpenACCCanContinue(); 9340e8b09c4SErich Keane } 935b1b46521Serichkeane ParsedClause.setLParenLoc(Parens.getOpenLocation()); 9360e8b09c4SErich Keane 93726fee0ffSErich Keane switch (ClauseKind) { 9380e8b09c4SErich Keane case OpenACCClauseKind::Default: { 939923f0392Serichkeane Token DefKindTok = getCurToken(); 9400e8b09c4SErich Keane 94161338782SErich Keane if (expectIdentifierOrKeyword(*this)) { 94261338782SErich Keane Parens.skipToEnd(); 94361338782SErich Keane return OpenACCCanContinue(); 94461338782SErich Keane } 9450e8b09c4SErich Keane 946923f0392Serichkeane ConsumeToken(); 9470e8b09c4SErich Keane 9480c7b92a4SErich Keane OpenACCDefaultClauseKind DefKind = 9490c7b92a4SErich Keane getOpenACCDefaultClauseKind(DefKindTok); 9500c7b92a4SErich Keane 95161338782SErich Keane if (DefKind == OpenACCDefaultClauseKind::Invalid) { 952923f0392Serichkeane Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); 95361338782SErich Keane Parens.skipToEnd(); 95461338782SErich Keane return OpenACCCanContinue(); 95561338782SErich Keane } 9560e8b09c4SErich Keane 95761338782SErich Keane ParsedClause.setDefaultDetails(DefKind); 9580e8b09c4SErich Keane break; 9590e8b09c4SErich Keane } 960e6b7c8c4Serichkeane case OpenACCClauseKind::If: { 961daa88364SErich Keane ExprResult CondExpr = ParseOpenACCConditionExpr(); 962daa88364SErich Keane ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() 963daa88364SErich Keane : nullptr); 964a6d1366bSerichkeane 96566ef6900Serichkeane if (CondExpr.isInvalid()) { 96666ef6900Serichkeane Parens.skipToEnd(); 96726fee0ffSErich Keane return OpenACCCanContinue(); 96866ef6900Serichkeane } 969daa88364SErich Keane 970e6b7c8c4Serichkeane break; 971e6b7c8c4Serichkeane } 9727b8f7f75Serichkeane case OpenACCClauseKind::CopyIn: 97301e91a2dSerichkeane case OpenACCClauseKind::PCopyIn: 97401e91a2dSerichkeane case OpenACCClauseKind::PresentOrCopyIn: { 97501e91a2dSerichkeane bool IsReadOnly = tryParseAndConsumeSpecialTokenKind( 97626fee0ffSErich Keane *this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind); 977a15b685cSErich Keane ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 978a15b685cSErich Keane IsReadOnly, 97901e91a2dSerichkeane /*IsZero=*/false); 9807b8f7f75Serichkeane break; 98101e91a2dSerichkeane } 9827b8f7f75Serichkeane case OpenACCClauseKind::Create: 98301e91a2dSerichkeane case OpenACCClauseKind::PCreate: 98401e91a2dSerichkeane case OpenACCClauseKind::PresentOrCreate: 985eca25bbdSerichkeane case OpenACCClauseKind::CopyOut: 98601e91a2dSerichkeane case OpenACCClauseKind::PCopyOut: 98701e91a2dSerichkeane case OpenACCClauseKind::PresentOrCopyOut: { 98801e91a2dSerichkeane bool IsZero = tryParseAndConsumeSpecialTokenKind( 98901e91a2dSerichkeane *this, OpenACCSpecialTokenKind::Zero, ClauseKind); 990a15b685cSErich Keane ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 99101e91a2dSerichkeane /*IsReadOnly=*/false, IsZero); 992eca25bbdSerichkeane break; 99301e91a2dSerichkeane } 994a15b685cSErich Keane case OpenACCClauseKind::Reduction: { 99539739552Serichkeane // If we're missing a clause-kind (or it is invalid), see if we can parse 99639739552Serichkeane // the var-list anyway. 997a15b685cSErich Keane OpenACCReductionOperator Op = ParseReductionOperator(*this); 998a15b685cSErich Keane ParsedClause.setReductionDetails(Op, ParseOpenACCVarList(ClauseKind)); 99939739552Serichkeane break; 1000a15b685cSErich Keane } 10019c4e7a15Serichkeane case OpenACCClauseKind::Self: 10029c4e7a15Serichkeane // The 'self' clause is a var-list instead of a 'condition' in the case of 10039c4e7a15Serichkeane // the 'update' clause, so we have to handle it here. Use an assert to 10049c4e7a15Serichkeane // make sure we get the right differentiator. 10059c4e7a15Serichkeane assert(DirKind == OpenACCDirectiveKind::Update); 1006*be32621cSerichkeane [[fallthrough]]; 1007*be32621cSerichkeane case OpenACCClauseKind::Device: 1008*be32621cSerichkeane case OpenACCClauseKind::Host: 10092c2accbcSerichkeane ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 10102c2accbcSerichkeane /*IsReadOnly=*/false, /*IsZero=*/false); 10112c2accbcSerichkeane break; 10127700ea10Serichkeane case OpenACCClauseKind::DeviceResident: 10137700ea10Serichkeane case OpenACCClauseKind::Link: 1014a15b685cSErich Keane ParseOpenACCVarList(ClauseKind); 1015fa67986dSErich Keane break; 101648c8a579Serichkeane case OpenACCClauseKind::Attach: 10171ab81f8eSerichkeane case OpenACCClauseKind::Delete: 10183351b3bfSerichkeane case OpenACCClauseKind::Detach: 101948c8a579Serichkeane case OpenACCClauseKind::DevicePtr: 1020fbb14dd9Serichkeane case OpenACCClauseKind::UseDevice: 1021a15b685cSErich Keane ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 102248c8a579Serichkeane /*IsReadOnly=*/false, /*IsZero=*/false); 102348c8a579Serichkeane break; 1024054f7c05Serichkeane case OpenACCClauseKind::Copy: 1025054f7c05Serichkeane case OpenACCClauseKind::PCopy: 1026054f7c05Serichkeane case OpenACCClauseKind::PresentOrCopy: 1027a13c5140Serichkeane case OpenACCClauseKind::FirstPrivate: 1028bd909d2eSerichkeane case OpenACCClauseKind::NoCreate: 1029bd909d2eSerichkeane case OpenACCClauseKind::Present: 1030fa67986dSErich Keane case OpenACCClauseKind::Private: 1031a15b685cSErich Keane ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 103201e91a2dSerichkeane /*IsReadOnly=*/false, /*IsZero=*/false); 1033923f0392Serichkeane break; 10343a82a1c3Serichkeane case OpenACCClauseKind::Collapse: { 103597da34e0SErich Keane bool HasForce = tryParseAndConsumeSpecialTokenKind( 103697da34e0SErich Keane *this, OpenACCSpecialTokenKind::Force, ClauseKind); 103797da34e0SErich Keane ExprResult LoopCount = 10380d8e333aSerichkeane getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 103997da34e0SErich Keane if (LoopCount.isInvalid()) { 104066ef6900Serichkeane Parens.skipToEnd(); 104126fee0ffSErich Keane return OpenACCCanContinue(); 104266ef6900Serichkeane } 104397da34e0SErich Keane 104497da34e0SErich Keane LoopCount = getActions().OpenACC().ActOnIntExpr( 104597da34e0SErich Keane OpenACCDirectiveKind::Invalid, ClauseKind, 104697da34e0SErich Keane LoopCount.get()->getBeginLoc(), LoopCount.get()); 104797da34e0SErich Keane 104897da34e0SErich Keane if (LoopCount.isInvalid()) { 104997da34e0SErich Keane Parens.skipToEnd(); 105097da34e0SErich Keane return OpenACCCanContinue(); 105197da34e0SErich Keane } 105297da34e0SErich Keane 105397da34e0SErich Keane ParsedClause.setCollapseDetails(HasForce, LoopCount.get()); 10543a82a1c3Serichkeane break; 10553a82a1c3Serichkeane } 105658b77b85Serichkeane case OpenACCClauseKind::Bind: { 105758b77b85Serichkeane ExprResult BindArg = ParseOpenACCBindClauseArgument(); 105866ef6900Serichkeane if (BindArg.isInvalid()) { 105966ef6900Serichkeane Parens.skipToEnd(); 106026fee0ffSErich Keane return OpenACCCanContinue(); 106166ef6900Serichkeane } 106258b77b85Serichkeane break; 106358b77b85Serichkeane } 1064dc20a0eaSErich Keane case OpenACCClauseKind::NumGangs: { 1065dc20a0eaSErich Keane llvm::SmallVector<Expr *> IntExprs; 1066dc20a0eaSErich Keane 1067dc20a0eaSErich Keane if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid, 1068dc20a0eaSErich Keane OpenACCClauseKind::NumGangs, ClauseLoc, 1069dc20a0eaSErich Keane IntExprs)) { 1070dc20a0eaSErich Keane Parens.skipToEnd(); 1071dc20a0eaSErich Keane return OpenACCCanContinue(); 1072dc20a0eaSErich Keane } 1073dc20a0eaSErich Keane ParsedClause.setIntExprDetails(std::move(IntExprs)); 1074dc20a0eaSErich Keane break; 1075dc20a0eaSErich Keane } 107604952c5bSerichkeane case OpenACCClauseKind::NumWorkers: 107704952c5bSerichkeane case OpenACCClauseKind::DeviceNum: 107804952c5bSerichkeane case OpenACCClauseKind::DefaultAsync: 10790d8e333aSerichkeane case OpenACCClauseKind::VectorLength: { 108076600aeeSErich Keane ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 1081dc20a0eaSErich Keane ClauseKind, ClauseLoc) 1082dc20a0eaSErich Keane .first; 108366ef6900Serichkeane if (IntExpr.isInvalid()) { 108466ef6900Serichkeane Parens.skipToEnd(); 108526fee0ffSErich Keane return OpenACCCanContinue(); 108666ef6900Serichkeane } 108776600aeeSErich Keane 108876600aeeSErich Keane ParsedClause.setIntExprDetails(IntExpr.get()); 10890d8e333aSerichkeane break; 10900d8e333aSerichkeane } 10912531a15dSerichkeane case OpenACCClauseKind::DType: 10928ef2011bSerichkeane case OpenACCClauseKind::DeviceType: { 10938ef2011bSerichkeane llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> Archs; 10942531a15dSerichkeane if (getCurToken().is(tok::star)) { 10952531a15dSerichkeane // FIXME: We want to mark that this is an 'everything else' type of 10962531a15dSerichkeane // device_type in Sema. 10978ef2011bSerichkeane ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}}); 10988ef2011bSerichkeane } else if (!ParseOpenACCDeviceTypeList(Archs)) { 10998ef2011bSerichkeane ParsedClause.setDeviceTypeDetails(std::move(Archs)); 11008ef2011bSerichkeane } else { 110166ef6900Serichkeane Parens.skipToEnd(); 110226fee0ffSErich Keane return OpenACCCanContinue(); 11032531a15dSerichkeane } 11042531a15dSerichkeane break; 11058ef2011bSerichkeane } 1106d412cea8SErich Keane case OpenACCClauseKind::Tile: { 1107d412cea8SErich Keane llvm::SmallVector<Expr *> SizeExprs; 1108d412cea8SErich Keane if (ParseOpenACCSizeExprList(OpenACCClauseKind::Tile, SizeExprs)) { 110966ef6900Serichkeane Parens.skipToEnd(); 111026fee0ffSErich Keane return OpenACCCanContinue(); 111166ef6900Serichkeane } 1112d412cea8SErich Keane 1113d412cea8SErich Keane ParsedClause.setIntExprDetails(std::move(SizeExprs)); 1114463529f3Serichkeane break; 1115d412cea8SErich Keane } 11160e8b09c4SErich Keane default: 11170e8b09c4SErich Keane llvm_unreachable("Not a required parens type?"); 11180e8b09c4SErich Keane } 11190e8b09c4SErich Keane 112026fee0ffSErich Keane ParsedClause.setEndLoc(getCurToken().getLocation()); 112126fee0ffSErich Keane 112226fee0ffSErich Keane if (Parens.consumeClose()) 112326fee0ffSErich Keane return OpenACCCannotContinue(); 112426fee0ffSErich Keane 112526fee0ffSErich Keane } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) { 112687f67c25Serichkeane if (!Parens.consumeOpen()) { 1127b1b46521Serichkeane ParsedClause.setLParenLoc(Parens.getOpenLocation()); 112826fee0ffSErich Keane switch (ClauseKind) { 112987f67c25Serichkeane case OpenACCClauseKind::Self: { 11309c4e7a15Serichkeane assert(DirKind != OpenACCDirectiveKind::Update); 1131daa88364SErich Keane ExprResult CondExpr = ParseOpenACCConditionExpr(); 113261338782SErich Keane ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() 113361338782SErich Keane : nullptr); 1134a6d1366bSerichkeane 113566ef6900Serichkeane if (CondExpr.isInvalid()) { 113666ef6900Serichkeane Parens.skipToEnd(); 113726fee0ffSErich Keane return OpenACCCanContinue(); 113866ef6900Serichkeane } 113987f67c25Serichkeane break; 11400e8b09c4SErich Keane } 11410dd72eb2Serichkeane case OpenACCClauseKind::Vector: 11420dd72eb2Serichkeane case OpenACCClauseKind::Worker: { 11430dd72eb2Serichkeane tryParseAndConsumeSpecialTokenKind(*this, 114426fee0ffSErich Keane ClauseKind == 114526fee0ffSErich Keane OpenACCClauseKind::Vector 11460dd72eb2Serichkeane ? OpenACCSpecialTokenKind::Length 11470dd72eb2Serichkeane : OpenACCSpecialTokenKind::Num, 114826fee0ffSErich Keane ClauseKind); 114976600aeeSErich Keane ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 1150dc20a0eaSErich Keane ClauseKind, ClauseLoc) 1151dc20a0eaSErich Keane .first; 115266ef6900Serichkeane if (IntExpr.isInvalid()) { 115366ef6900Serichkeane Parens.skipToEnd(); 115426fee0ffSErich Keane return OpenACCCanContinue(); 115566ef6900Serichkeane } 1156cf456ed2SErich Keane ParsedClause.setIntExprDetails(IntExpr.get()); 11570dd72eb2Serichkeane break; 11580dd72eb2Serichkeane } 115962a384caSerichkeane case OpenACCClauseKind::Async: { 116030cfe2b2Serichkeane ExprResult AsyncArg = 116130cfe2b2Serichkeane ParseOpenACCAsyncArgument(OpenACCDirectiveKind::Invalid, 116230cfe2b2Serichkeane OpenACCClauseKind::Async, ClauseLoc) 116330cfe2b2Serichkeane .first; 116430cfe2b2Serichkeane ParsedClause.setIntExprDetails(AsyncArg.isUsable() ? AsyncArg.get() 116530cfe2b2Serichkeane : nullptr); 116666ef6900Serichkeane if (AsyncArg.isInvalid()) { 116766ef6900Serichkeane Parens.skipToEnd(); 116826fee0ffSErich Keane return OpenACCCanContinue(); 116966ef6900Serichkeane } 117062a384caSerichkeane break; 117162a384caSerichkeane } 11725b25c313SErich Keane case OpenACCClauseKind::Gang: { 11735b25c313SErich Keane llvm::SmallVector<OpenACCGangKind> GKs; 11745b25c313SErich Keane llvm::SmallVector<Expr *> IntExprs; 11755b25c313SErich Keane if (ParseOpenACCGangArgList(ClauseLoc, GKs, IntExprs)) { 117666ef6900Serichkeane Parens.skipToEnd(); 117726fee0ffSErich Keane return OpenACCCanContinue(); 117866ef6900Serichkeane } 11795b25c313SErich Keane ParsedClause.setGangDetails(std::move(GKs), std::move(IntExprs)); 1180b52fe2dfSerichkeane break; 11815b25c313SErich Keane } 1182b1b46521Serichkeane case OpenACCClauseKind::Wait: { 1183b1b46521Serichkeane OpenACCWaitParseInfo Info = 1184b1b46521Serichkeane ParseOpenACCWaitArgument(ClauseLoc, 1185b1b46521Serichkeane /*IsDirective=*/false); 1186b1b46521Serichkeane if (Info.Failed) { 11870dd0cbd3Serichkeane Parens.skipToEnd(); 118826fee0ffSErich Keane return OpenACCCanContinue(); 11890dd0cbd3Serichkeane } 1190b1b46521Serichkeane 1191b1b46521Serichkeane ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc, 1192b1b46521Serichkeane std::move(Info.QueueIdExprs)); 11930dd0cbd3Serichkeane break; 1194b1b46521Serichkeane } 119587f67c25Serichkeane default: 119687f67c25Serichkeane llvm_unreachable("Not an optional parens type?"); 119787f67c25Serichkeane } 119826fee0ffSErich Keane ParsedClause.setEndLoc(getCurToken().getLocation()); 119926fee0ffSErich Keane if (Parens.consumeClose()) 120026fee0ffSErich Keane return OpenACCCannotContinue(); 12018d2ab2a0Serichkeane } else { 12028d2ab2a0Serichkeane // If we have optional parens, make sure we set the end-location to the 12038d2ab2a0Serichkeane // clause, as we are a 'single token' clause. 12048d2ab2a0Serichkeane ParsedClause.setEndLoc(ClauseLoc); 120587f67c25Serichkeane } 12062b939e18Serichkeane } else { 12072b939e18Serichkeane ParsedClause.setEndLoc(ClauseLoc); 120887f67c25Serichkeane } 120926fee0ffSErich Keane return OpenACCSuccess( 121026fee0ffSErich Keane Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause)); 12110e8b09c4SErich Keane } 12120e8b09c4SErich Keane 121362a384caSerichkeane /// OpenACC 3.3 section 2.16: 121462a384caSerichkeane /// In this section and throughout the specification, the term async-argument 121562a384caSerichkeane /// means a nonnegative scalar integer expression (int for C or C++, integer for 121662a384caSerichkeane /// Fortran), or one of the special values acc_async_noval or acc_async_sync, as 121762a384caSerichkeane /// defined in the C header file and the Fortran openacc module. The special 121862a384caSerichkeane /// values are negative values, so as not to conflict with a user-specified 121962a384caSerichkeane /// nonnegative async-argument. 122030cfe2b2Serichkeane Parser::OpenACCIntExprParseResult 122130cfe2b2Serichkeane Parser::ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, OpenACCClauseKind CK, 122230cfe2b2Serichkeane SourceLocation Loc) { 122330cfe2b2Serichkeane return ParseOpenACCIntExpr(DK, CK, Loc); 122462a384caSerichkeane } 122562a384caSerichkeane 1226df3db035SErich Keane /// OpenACC 3.3, section 2.16: 1227df3db035SErich Keane /// In this section and throughout the specification, the term wait-argument 1228df3db035SErich Keane /// means: 1229df3db035SErich Keane /// [ devnum : int-expr : ] [ queues : ] async-argument-list 1230b1b46521Serichkeane Parser::OpenACCWaitParseInfo 1231b1b46521Serichkeane Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) { 1232b1b46521Serichkeane OpenACCWaitParseInfo Result; 1233df3db035SErich Keane // [devnum : int-expr : ] 1234df3db035SErich Keane if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && 1235df3db035SErich Keane NextToken().is(tok::colon)) { 1236df3db035SErich Keane // Consume devnum. 1237df3db035SErich Keane ConsumeToken(); 1238df3db035SErich Keane // Consume colon. 1239df3db035SErich Keane ConsumeToken(); 1240df3db035SErich Keane 124130cfe2b2Serichkeane OpenACCIntExprParseResult Res = ParseOpenACCIntExpr( 124230cfe2b2Serichkeane IsDirective ? OpenACCDirectiveKind::Wait 124376600aeeSErich Keane : OpenACCDirectiveKind::Invalid, 124430cfe2b2Serichkeane IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, 124530cfe2b2Serichkeane Loc); 1246b1b46521Serichkeane if (Res.first.isInvalid() && 1247b1b46521Serichkeane Res.second == OpenACCParseCanContinue::Cannot) { 1248b1b46521Serichkeane Result.Failed = true; 1249b1b46521Serichkeane return Result; 1250b1b46521Serichkeane } 1251df3db035SErich Keane 1252b1b46521Serichkeane if (ExpectAndConsume(tok::colon)) { 1253b1b46521Serichkeane Result.Failed = true; 1254b1b46521Serichkeane return Result; 1255b1b46521Serichkeane } 1256b1b46521Serichkeane 1257b1b46521Serichkeane Result.DevNumExpr = Res.first.get(); 1258df3db035SErich Keane } 1259df3db035SErich Keane 1260df3db035SErich Keane // [ queues : ] 1261df3db035SErich Keane if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && 1262df3db035SErich Keane NextToken().is(tok::colon)) { 1263df3db035SErich Keane // Consume queues. 1264b1b46521Serichkeane Result.QueuesLoc = ConsumeToken(); 1265df3db035SErich Keane // Consume colon. 1266df3db035SErich Keane ConsumeToken(); 1267df3db035SErich Keane } 1268df3db035SErich Keane 1269df3db035SErich Keane // OpenACC 3.3, section 2.16: 1270df3db035SErich Keane // the term 'async-argument' means a nonnegative scalar integer expression, or 1271df3db035SErich Keane // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined 1272df3db035SErich Keane // in the C header file and the Fortran opacc module. 1273df3db035SErich Keane bool FirstArg = true; 1274df3db035SErich Keane while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 1275df3db035SErich Keane if (!FirstArg) { 1276b1b46521Serichkeane if (ExpectAndConsume(tok::comma)) { 1277b1b46521Serichkeane Result.Failed = true; 1278b1b46521Serichkeane return Result; 1279b1b46521Serichkeane } 1280df3db035SErich Keane } 1281df3db035SErich Keane FirstArg = false; 1282df3db035SErich Keane 128330cfe2b2Serichkeane OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument( 128430cfe2b2Serichkeane IsDirective ? OpenACCDirectiveKind::Wait 128530cfe2b2Serichkeane : OpenACCDirectiveKind::Invalid, 128630cfe2b2Serichkeane IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, 128730cfe2b2Serichkeane Loc); 1288df3db035SErich Keane 1289b1b46521Serichkeane if (Res.first.isInvalid() && 1290b1b46521Serichkeane Res.second == OpenACCParseCanContinue::Cannot) { 1291b1b46521Serichkeane Result.Failed = true; 1292b1b46521Serichkeane return Result; 1293df3db035SErich Keane } 1294df3db035SErich Keane 1295e34cc7c9Serichkeane if (Res.first.isUsable()) 1296b1b46521Serichkeane Result.QueueIdExprs.push_back(Res.first.get()); 1297b1b46521Serichkeane } 1298b1b46521Serichkeane 1299b1b46521Serichkeane return Result; 1300df3db035SErich Keane } 1301df3db035SErich Keane 1302721558aeSErich Keane ExprResult Parser::ParseOpenACCIDExpression() { 1303ba1c869fSErich Keane ExprResult Res; 1304ba1c869fSErich Keane if (getLangOpts().CPlusPlus) { 130558b77b85Serichkeane Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true); 1306ba1c869fSErich Keane } else { 1307ba1c869fSErich Keane // There isn't anything quite the same as ParseCXXIdExpression for C, so we 1308ba1c869fSErich Keane // need to get the identifier, then call into Sema ourselves. 1309ba1c869fSErich Keane 1310721558aeSErich Keane if (Tok.isNot(tok::identifier)) { 1311721558aeSErich Keane Diag(Tok, diag::err_expected) << tok::identifier; 1312ba1c869fSErich Keane return ExprError(); 1313721558aeSErich Keane } 1314ba1c869fSErich Keane 1315ba1c869fSErich Keane Token FuncName = getCurToken(); 1316ba1c869fSErich Keane UnqualifiedId Name; 1317ba1c869fSErich Keane CXXScopeSpec ScopeSpec; 1318ba1c869fSErich Keane SourceLocation TemplateKWLoc; 1319ba1c869fSErich Keane Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken()); 1320ba1c869fSErich Keane 1321ba1c869fSErich Keane // Ensure this is a valid identifier. We don't accept causing implicit 1322ba1c869fSErich Keane // function declarations per the spec, so always claim to not have trailing 1323ba1c869fSErich Keane // L Paren. 1324ba1c869fSErich Keane Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, 1325ba1c869fSErich Keane Name, /*HasTrailingLParen=*/false, 1326ba1c869fSErich Keane /*isAddressOfOperand=*/false); 1327ba1c869fSErich Keane } 1328ba1c869fSErich Keane 1329ba1c869fSErich Keane return getActions().CorrectDelayedTyposInExpr(Res); 1330ba1c869fSErich Keane } 1331ba1c869fSErich Keane 133258b77b85Serichkeane ExprResult Parser::ParseOpenACCBindClauseArgument() { 133358b77b85Serichkeane // OpenACC 3.3 section 2.15: 133458b77b85Serichkeane // The bind clause specifies the name to use when calling the procedure on a 133558b77b85Serichkeane // device other than the host. If the name is specified as an identifier, it 133658b77b85Serichkeane // is called as if that name were specified in the language being compiled. If 133758b77b85Serichkeane // the name is specified as a string, the string is used for the procedure 133858b77b85Serichkeane // name unmodified. 133958b77b85Serichkeane if (getCurToken().is(tok::r_paren)) { 134058b77b85Serichkeane Diag(getCurToken(), diag::err_acc_incorrect_bind_arg); 134158b77b85Serichkeane return ExprError(); 134258b77b85Serichkeane } 134358b77b85Serichkeane 134458b77b85Serichkeane if (tok::isStringLiteral(getCurToken().getKind())) 134558b77b85Serichkeane return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression( 134658b77b85Serichkeane /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true)); 134758b77b85Serichkeane 134858b77b85Serichkeane return ParseOpenACCIDExpression(); 134958b77b85Serichkeane } 135058b77b85Serichkeane 1351cac6b1a5SErich Keane /// OpenACC 3.3, section 1.6: 1352cac6b1a5SErich Keane /// In this spec, a 'var' (in italics) is one of the following: 1353fa67986dSErich Keane /// - a variable name (a scalar, array, or composite variable name) 1354cac6b1a5SErich Keane /// - a subarray specification with subscript ranges 1355cac6b1a5SErich Keane /// - an array element 1356cac6b1a5SErich Keane /// - a member of a composite variable 1357cac6b1a5SErich Keane /// - a common block name between slashes (fortran only) 1358a15b685cSErich Keane Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCClauseKind CK) { 1359cac6b1a5SErich Keane OpenACCArraySectionRAII ArraySections(*this); 1360fa67986dSErich Keane 1361fa67986dSErich Keane ExprResult Res = ParseAssignmentExpression(); 1362fa67986dSErich Keane if (!Res.isUsable()) 1363fa67986dSErich Keane return {Res, OpenACCParseCanContinue::Cannot}; 1364fa67986dSErich Keane 1365fa67986dSErich Keane Res = getActions().CorrectDelayedTyposInExpr(Res.get()); 1366fa67986dSErich Keane if (!Res.isUsable()) 1367fa67986dSErich Keane return {Res, OpenACCParseCanContinue::Can}; 1368fa67986dSErich Keane 1369a15b685cSErich Keane Res = getActions().OpenACC().ActOnVar(CK, Res.get()); 1370fa67986dSErich Keane 1371fa67986dSErich Keane return {Res, OpenACCParseCanContinue::Can}; 1372fa67986dSErich Keane } 1373fa67986dSErich Keane 1374a15b685cSErich Keane llvm::SmallVector<Expr *> Parser::ParseOpenACCVarList(OpenACCClauseKind CK) { 1375fa67986dSErich Keane llvm::SmallVector<Expr *> Vars; 1376fa67986dSErich Keane 1377a15b685cSErich Keane auto [Res, CanContinue] = ParseOpenACCVar(CK); 1378fa67986dSErich Keane if (Res.isUsable()) { 1379fa67986dSErich Keane Vars.push_back(Res.get()); 1380fa67986dSErich Keane } else if (CanContinue == OpenACCParseCanContinue::Cannot) { 1381fa67986dSErich Keane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch); 1382fa67986dSErich Keane return Vars; 1383fa67986dSErich Keane } 1384fa67986dSErich Keane 1385fa67986dSErich Keane while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 1386fa67986dSErich Keane ExpectAndConsume(tok::comma); 1387fa67986dSErich Keane 1388a15b685cSErich Keane auto [Res, CanContinue] = ParseOpenACCVar(CK); 1389fa67986dSErich Keane 1390fa67986dSErich Keane if (Res.isUsable()) { 1391fa67986dSErich Keane Vars.push_back(Res.get()); 1392fa67986dSErich Keane } else if (CanContinue == OpenACCParseCanContinue::Cannot) { 1393fa67986dSErich Keane SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch); 1394fa67986dSErich Keane return Vars; 1395fa67986dSErich Keane } 1396fa67986dSErich Keane } 1397fa67986dSErich Keane return Vars; 1398721558aeSErich Keane } 1399721558aeSErich Keane 1400721558aeSErich Keane /// OpenACC 3.3, section 2.10: 1401721558aeSErich Keane /// In C and C++, the syntax of the cache directive is: 1402721558aeSErich Keane /// 1403721558aeSErich Keane /// #pragma acc cache ([readonly:]var-list) new-line 1404721558aeSErich Keane void Parser::ParseOpenACCCacheVarList() { 1405721558aeSErich Keane // If this is the end of the line, just return 'false' and count on the close 1406721558aeSErich Keane // paren diagnostic to catch the issue. 1407721558aeSErich Keane if (getCurToken().isAnnotation()) 1408721558aeSErich Keane return; 1409721558aeSErich Keane 1410721558aeSErich Keane // The VarList is an optional `readonly:` followed by a list of a variable 14119e068cd7SErich Keane // specifications. Consume something that looks like a 'tag', and diagnose if 14129e068cd7SErich Keane // it isn't 'readonly'. 1413d5000e9cSerichkeane if (tryParseAndConsumeSpecialTokenKind(*this, 14149e068cd7SErich Keane OpenACCSpecialTokenKind::ReadOnly, 14159e068cd7SErich Keane OpenACCDirectiveKind::Cache)) { 1416721558aeSErich Keane // FIXME: Record that this is a 'readonly' so that we can use that during 1417721558aeSErich Keane // Sema/AST generation. 1418721558aeSErich Keane } 1419721558aeSErich Keane 1420fa67986dSErich Keane // ParseOpenACCVarList should leave us before a r-paren, so no need to skip 1421fa67986dSErich Keane // anything here. 1422a15b685cSErich Keane ParseOpenACCVarList(OpenACCClauseKind::Invalid); 1423721558aeSErich Keane } 1424721558aeSErich Keane 1425193e9007Serichkeane Parser::OpenACCDirectiveParseInfo 1426193e9007Serichkeane Parser::ParseOpenACCDirective() { 1427193e9007Serichkeane SourceLocation StartLoc = ConsumeAnnotationToken(); 1428193e9007Serichkeane SourceLocation DirLoc = getCurToken().getLocation(); 1429ba1c869fSErich Keane OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); 1430e34cc7c9Serichkeane Parser::OpenACCWaitParseInfo WaitInfo; 143104e9b61cSErich Keane 1432193e9007Serichkeane getActions().OpenACC().ActOnConstruct(DirKind, DirLoc); 143324144d72SErich Keane 143404e9b61cSErich Keane // Once we've parsed the construct/directive name, some have additional 143504e9b61cSErich Keane // specifiers that need to be taken care of. Atomic has an 'atomic-clause' 143604e9b61cSErich Keane // that needs to be parsed. 143704e9b61cSErich Keane if (DirKind == OpenACCDirectiveKind::Atomic) 1438ba1c869fSErich Keane ParseOpenACCAtomicKind(*this); 143964b6ef02SErich Keane 1440ba1c869fSErich Keane // We've successfully parsed the construct/directive name, however a few of 1441ba1c869fSErich Keane // the constructs have optional parens that contain further details. 1442ba1c869fSErich Keane BalancedDelimiterTracker T(*this, tok::l_paren, 1443ba1c869fSErich Keane tok::annot_pragma_openacc_end); 144464b6ef02SErich Keane 1445ba1c869fSErich Keane if (!T.consumeOpen()) { 1446ba1c869fSErich Keane switch (DirKind) { 1447ba1c869fSErich Keane default: 1448ba1c869fSErich Keane Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren); 1449ba1c869fSErich Keane T.skipToEnd(); 1450ba1c869fSErich Keane break; 1451ba1c869fSErich Keane case OpenACCDirectiveKind::Routine: { 1452721558aeSErich Keane // Routine has an optional paren-wrapped name of a function in the local 1453721558aeSErich Keane // scope. We parse the name, emitting any diagnostics 1454721558aeSErich Keane ExprResult RoutineName = ParseOpenACCIDExpression(); 1455ba1c869fSErich Keane // If the routine name is invalid, just skip until the closing paren to 1456ba1c869fSErich Keane // recover more gracefully. 1457ba1c869fSErich Keane if (RoutineName.isInvalid()) 1458ba1c869fSErich Keane T.skipToEnd(); 1459ba1c869fSErich Keane else 1460ba1c869fSErich Keane T.consumeClose(); 1461ba1c869fSErich Keane break; 1462ba1c869fSErich Keane } 1463721558aeSErich Keane case OpenACCDirectiveKind::Cache: 1464721558aeSErich Keane ParseOpenACCCacheVarList(); 1465721558aeSErich Keane // The ParseOpenACCCacheVarList function manages to recover from failures, 1466721558aeSErich Keane // so we can always consume the close. 1467721558aeSErich Keane T.consumeClose(); 1468721558aeSErich Keane break; 1469df3db035SErich Keane case OpenACCDirectiveKind::Wait: 1470df3db035SErich Keane // OpenACC has an optional paren-wrapped 'wait-argument'. 1471e34cc7c9Serichkeane WaitInfo = ParseOpenACCWaitArgument(DirLoc, /*IsDirective=*/true); 1472e34cc7c9Serichkeane if (WaitInfo.Failed) 1473df3db035SErich Keane T.skipToEnd(); 1474df3db035SErich Keane else 1475df3db035SErich Keane T.consumeClose(); 1476df3db035SErich Keane break; 1477ba1c869fSErich Keane } 1478721558aeSErich Keane } else if (DirKind == OpenACCDirectiveKind::Cache) { 1479721558aeSErich Keane // Cache's paren var-list is required, so error here if it isn't provided. 1480721558aeSErich Keane // We know that the consumeOpen above left the first non-paren here, so 1481721558aeSErich Keane // diagnose, then continue as if it was completely omitted. 1482721558aeSErich Keane Diag(Tok, diag::err_expected) << tok::l_paren; 148364b6ef02SErich Keane } 148464b6ef02SErich Keane 148526fee0ffSErich Keane // Parses the list of clauses, if present, plus set up return value. 1486e34cc7c9Serichkeane OpenACCDirectiveParseInfo ParseInfo{DirKind, 1487e34cc7c9Serichkeane StartLoc, 1488e34cc7c9Serichkeane DirLoc, 1489e34cc7c9Serichkeane T.getOpenLocation(), 1490e34cc7c9Serichkeane T.getCloseLocation(), 1491e34cc7c9Serichkeane /*EndLoc=*/SourceLocation{}, 1492e34cc7c9Serichkeane WaitInfo.QueuesLoc, 1493e34cc7c9Serichkeane WaitInfo.getAllExprs(), 149426fee0ffSErich Keane ParseOpenACCClauseList(DirKind)}; 1495ba1c869fSErich Keane 1496fdee0a35SErich Keane assert(Tok.is(tok::annot_pragma_openacc_end) && 1497fdee0a35SErich Keane "Didn't parse all OpenACC Clauses"); 149826fee0ffSErich Keane ParseInfo.EndLoc = ConsumeAnnotationToken(); 14994d6e67f6Serichkeane assert(ParseInfo.EndLoc.isValid() && 150026fee0ffSErich Keane "Terminating annotation token not present"); 150124144d72SErich Keane 150226fee0ffSErich Keane return ParseInfo; 1503ba1c869fSErich Keane } 150464b6ef02SErich Keane 150564b6ef02SErich Keane // Parse OpenACC directive on a declaration. 15067d1a9e81Serichkeane Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { 150764b6ef02SErich Keane assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 150864b6ef02SErich Keane 150964b6ef02SErich Keane ParsingOpenACCDirectiveRAII DirScope(*this); 151064b6ef02SErich Keane 151124144d72SErich Keane OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); 151264b6ef02SErich Keane 1513e45f6e56SVlad Serebrennikov if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind, 151424144d72SErich Keane DirInfo.StartLoc)) 1515ff219ea9SErich Keane return nullptr; 151624144d72SErich Keane 151724144d72SErich Keane // TODO OpenACC: Do whatever decl parsing is required here. 1518e45f6e56SVlad Serebrennikov return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective()); 1519ff219ea9SErich Keane } 152064b6ef02SErich Keane 152164b6ef02SErich Keane // Parse OpenACC Directive on a Statement. 1522ff219ea9SErich Keane StmtResult Parser::ParseOpenACCDirectiveStmt() { 152364b6ef02SErich Keane assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 152464b6ef02SErich Keane 152564b6ef02SErich Keane ParsingOpenACCDirectiveRAII DirScope(*this); 152664b6ef02SErich Keane 152724144d72SErich Keane OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); 1528bfc2dbe0Serichkeane if (getActions().OpenACC().ActOnStartStmtDirective( 1529bfc2dbe0Serichkeane DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses)) 153024144d72SErich Keane return StmtError(); 153164b6ef02SErich Keane 153224144d72SErich Keane StmtResult AssocStmt; 153324144d72SErich Keane if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) { 1534010d0115Serichkeane SemaOpenACC::AssociatedStmtRAII AssocStmtRAII( 1535010d0115Serichkeane getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {}, 1536010d0115Serichkeane DirInfo.Clauses); 153724144d72SErich Keane ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false); 153826cc6f12SErich Keane ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind)); 153926cc6f12SErich Keane 154042f4e505SErich Keane AssocStmt = getActions().OpenACC().ActOnAssociatedStmt( 1541b0cfbfd7SErich Keane DirInfo.StartLoc, DirInfo.DirKind, DirInfo.Clauses, ParseStatement()); 154224144d72SErich Keane } 154324144d72SErich Keane 1544e45f6e56SVlad Serebrennikov return getActions().OpenACC().ActOnEndStmtDirective( 1545e34cc7c9Serichkeane DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc, 1546e34cc7c9Serichkeane DirInfo.MiscLoc, DirInfo.Exprs, DirInfo.RParenLoc, DirInfo.EndLoc, 1547193e9007Serichkeane DirInfo.Clauses, AssocStmt); 1548ff219ea9SErich Keane } 1549