15f757f3fSDimitry Andric //===--- ParseOpenACC.cpp - OpenACC-specific parsing support --------------===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric // 95f757f3fSDimitry Andric // This file implements the parsing logic for OpenACC language features. 105f757f3fSDimitry Andric // 115f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 125f757f3fSDimitry Andric 135f757f3fSDimitry Andric #include "clang/Basic/OpenACCKinds.h" 145f757f3fSDimitry Andric #include "clang/Parse/ParseDiagnostic.h" 155f757f3fSDimitry Andric #include "clang/Parse/Parser.h" 165f757f3fSDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h" 175f757f3fSDimitry Andric #include "llvm/ADT/StringRef.h" 185f757f3fSDimitry Andric #include "llvm/ADT/StringSwitch.h" 195f757f3fSDimitry Andric 205f757f3fSDimitry Andric using namespace clang; 215f757f3fSDimitry Andric using namespace llvm; 225f757f3fSDimitry Andric 235f757f3fSDimitry Andric namespace { 245f757f3fSDimitry Andric // An enum that contains the extended 'partial' parsed variants. This type 255f757f3fSDimitry Andric // should never escape the initial parse functionality, but is useful for 265f757f3fSDimitry Andric // simplifying the implementation. 275f757f3fSDimitry Andric enum class OpenACCDirectiveKindEx { 285f757f3fSDimitry Andric Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid), 295f757f3fSDimitry Andric // 'enter data' and 'exit data' 305f757f3fSDimitry Andric Enter, 315f757f3fSDimitry Andric Exit, 325f757f3fSDimitry Andric }; 335f757f3fSDimitry Andric 345f757f3fSDimitry Andric // Translate single-token string representations to the OpenACC Directive Kind. 355f757f3fSDimitry Andric // This doesn't completely comprehend 'Compound Constructs' (as it just 365f757f3fSDimitry Andric // identifies the first token), and doesn't fully handle 'enter data', 'exit 375f757f3fSDimitry Andric // data', nor any of the 'atomic' variants, just the first token of each. So 385f757f3fSDimitry Andric // this should only be used by `ParseOpenACCDirectiveKind`. 395f757f3fSDimitry Andric OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { 405f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 415f757f3fSDimitry Andric return OpenACCDirectiveKindEx::Invalid; 425f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = 435f757f3fSDimitry Andric llvm::StringSwitch<OpenACCDirectiveKind>( 445f757f3fSDimitry Andric Tok.getIdentifierInfo()->getName()) 455f757f3fSDimitry Andric .Case("parallel", OpenACCDirectiveKind::Parallel) 465f757f3fSDimitry Andric .Case("serial", OpenACCDirectiveKind::Serial) 475f757f3fSDimitry Andric .Case("kernels", OpenACCDirectiveKind::Kernels) 485f757f3fSDimitry Andric .Case("data", OpenACCDirectiveKind::Data) 495f757f3fSDimitry Andric .Case("host_data", OpenACCDirectiveKind::HostData) 505f757f3fSDimitry Andric .Case("loop", OpenACCDirectiveKind::Loop) 515f757f3fSDimitry Andric .Case("cache", OpenACCDirectiveKind::Cache) 525f757f3fSDimitry Andric .Case("atomic", OpenACCDirectiveKind::Atomic) 535f757f3fSDimitry Andric .Case("routine", OpenACCDirectiveKind::Routine) 545f757f3fSDimitry Andric .Case("declare", OpenACCDirectiveKind::Declare) 555f757f3fSDimitry Andric .Case("init", OpenACCDirectiveKind::Init) 565f757f3fSDimitry Andric .Case("shutdown", OpenACCDirectiveKind::Shutdown) 575f757f3fSDimitry Andric .Case("set", OpenACCDirectiveKind::Shutdown) 585f757f3fSDimitry Andric .Case("update", OpenACCDirectiveKind::Update) 595f757f3fSDimitry Andric .Case("wait", OpenACCDirectiveKind::Wait) 605f757f3fSDimitry Andric .Default(OpenACCDirectiveKind::Invalid); 615f757f3fSDimitry Andric 625f757f3fSDimitry Andric if (DirKind != OpenACCDirectiveKind::Invalid) 635f757f3fSDimitry Andric return static_cast<OpenACCDirectiveKindEx>(DirKind); 645f757f3fSDimitry Andric 655f757f3fSDimitry Andric return llvm::StringSwitch<OpenACCDirectiveKindEx>( 665f757f3fSDimitry Andric Tok.getIdentifierInfo()->getName()) 675f757f3fSDimitry Andric .Case("enter", OpenACCDirectiveKindEx::Enter) 685f757f3fSDimitry Andric .Case("exit", OpenACCDirectiveKindEx::Exit) 695f757f3fSDimitry Andric .Default(OpenACCDirectiveKindEx::Invalid); 705f757f3fSDimitry Andric } 715f757f3fSDimitry Andric 72cb14a3feSDimitry Andric // Translate single-token string representations to the OpenCC Clause Kind. 73cb14a3feSDimitry Andric OpenACCClauseKind getOpenACCClauseKind(Token Tok) { 74cb14a3feSDimitry Andric // auto is a keyword in some language modes, so make sure we parse it 75cb14a3feSDimitry Andric // correctly. 76cb14a3feSDimitry Andric if (Tok.is(tok::kw_auto)) 77cb14a3feSDimitry Andric return OpenACCClauseKind::Auto; 78cb14a3feSDimitry Andric 791db9f3b2SDimitry Andric // default is a keyword, so make sure we parse it correctly. 801db9f3b2SDimitry Andric if (Tok.is(tok::kw_default)) 811db9f3b2SDimitry Andric return OpenACCClauseKind::Default; 821db9f3b2SDimitry Andric 831db9f3b2SDimitry Andric // if is also a keyword, make sure we parse it correctly. 841db9f3b2SDimitry Andric if (Tok.is(tok::kw_if)) 851db9f3b2SDimitry Andric return OpenACCClauseKind::If; 861db9f3b2SDimitry Andric 87cb14a3feSDimitry Andric if (!Tok.is(tok::identifier)) 88cb14a3feSDimitry Andric return OpenACCClauseKind::Invalid; 89cb14a3feSDimitry Andric 90cb14a3feSDimitry Andric return llvm::StringSwitch<OpenACCClauseKind>( 91cb14a3feSDimitry Andric Tok.getIdentifierInfo()->getName()) 92*7a6dacacSDimitry Andric .Case("attach", OpenACCClauseKind::Attach) 93cb14a3feSDimitry Andric .Case("auto", OpenACCClauseKind::Auto) 94*7a6dacacSDimitry Andric .Case("bind", OpenACCClauseKind::Bind) 95*7a6dacacSDimitry Andric .Case("create", OpenACCClauseKind::Create) 96*7a6dacacSDimitry Andric .Case("collapse", OpenACCClauseKind::Collapse) 97*7a6dacacSDimitry Andric .Case("copy", OpenACCClauseKind::Copy) 98*7a6dacacSDimitry Andric .Case("copyin", OpenACCClauseKind::CopyIn) 99*7a6dacacSDimitry Andric .Case("copyout", OpenACCClauseKind::CopyOut) 1001db9f3b2SDimitry Andric .Case("default", OpenACCClauseKind::Default) 101*7a6dacacSDimitry Andric .Case("default_async", OpenACCClauseKind::DefaultAsync) 102*7a6dacacSDimitry Andric .Case("delete", OpenACCClauseKind::Delete) 103*7a6dacacSDimitry Andric .Case("detach", OpenACCClauseKind::Detach) 104*7a6dacacSDimitry Andric .Case("device", OpenACCClauseKind::Device) 105*7a6dacacSDimitry Andric .Case("device_num", OpenACCClauseKind::DeviceNum) 106*7a6dacacSDimitry Andric .Case("device_resident", OpenACCClauseKind::DeviceResident) 107*7a6dacacSDimitry Andric .Case("device_type", OpenACCClauseKind::DeviceType) 108*7a6dacacSDimitry Andric .Case("deviceptr", OpenACCClauseKind::DevicePtr) 109*7a6dacacSDimitry Andric .Case("dtype", OpenACCClauseKind::DType) 110cb14a3feSDimitry Andric .Case("finalize", OpenACCClauseKind::Finalize) 111*7a6dacacSDimitry Andric .Case("firstprivate", OpenACCClauseKind::FirstPrivate) 112*7a6dacacSDimitry Andric .Case("host", OpenACCClauseKind::Host) 1131db9f3b2SDimitry Andric .Case("if", OpenACCClauseKind::If) 114cb14a3feSDimitry Andric .Case("if_present", OpenACCClauseKind::IfPresent) 115cb14a3feSDimitry Andric .Case("independent", OpenACCClauseKind::Independent) 116*7a6dacacSDimitry Andric .Case("link", OpenACCClauseKind::Link) 117*7a6dacacSDimitry Andric .Case("no_create", OpenACCClauseKind::NoCreate) 118*7a6dacacSDimitry Andric .Case("num_gangs", OpenACCClauseKind::NumGangs) 119*7a6dacacSDimitry Andric .Case("num_workers", OpenACCClauseKind::NumWorkers) 120cb14a3feSDimitry Andric .Case("nohost", OpenACCClauseKind::NoHost) 121*7a6dacacSDimitry Andric .Case("present", OpenACCClauseKind::Present) 122*7a6dacacSDimitry Andric .Case("private", OpenACCClauseKind::Private) 123*7a6dacacSDimitry Andric .Case("reduction", OpenACCClauseKind::Reduction) 1241db9f3b2SDimitry Andric .Case("self", OpenACCClauseKind::Self) 125cb14a3feSDimitry Andric .Case("seq", OpenACCClauseKind::Seq) 126*7a6dacacSDimitry Andric .Case("use_device", OpenACCClauseKind::UseDevice) 127cb14a3feSDimitry Andric .Case("vector", OpenACCClauseKind::Vector) 128*7a6dacacSDimitry Andric .Case("vector_length", OpenACCClauseKind::VectorLength) 129cb14a3feSDimitry Andric .Case("worker", OpenACCClauseKind::Worker) 130cb14a3feSDimitry Andric .Default(OpenACCClauseKind::Invalid); 131cb14a3feSDimitry Andric } 132cb14a3feSDimitry Andric 1335f757f3fSDimitry Andric // Since 'atomic' is effectively a compound directive, this will decode the 1345f757f3fSDimitry Andric // second part of the directive. 1355f757f3fSDimitry Andric OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { 1365f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 1375f757f3fSDimitry Andric return OpenACCAtomicKind::Invalid; 1385f757f3fSDimitry Andric return llvm::StringSwitch<OpenACCAtomicKind>( 1395f757f3fSDimitry Andric Tok.getIdentifierInfo()->getName()) 1405f757f3fSDimitry Andric .Case("read", OpenACCAtomicKind::Read) 1415f757f3fSDimitry Andric .Case("write", OpenACCAtomicKind::Write) 1425f757f3fSDimitry Andric .Case("update", OpenACCAtomicKind::Update) 1435f757f3fSDimitry Andric .Case("capture", OpenACCAtomicKind::Capture) 1445f757f3fSDimitry Andric .Default(OpenACCAtomicKind::Invalid); 1455f757f3fSDimitry Andric } 1465f757f3fSDimitry Andric 1471db9f3b2SDimitry Andric OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) { 1481db9f3b2SDimitry Andric if (!Tok.is(tok::identifier)) 1491db9f3b2SDimitry Andric return OpenACCDefaultClauseKind::Invalid; 1501db9f3b2SDimitry Andric 1511db9f3b2SDimitry Andric return llvm::StringSwitch<OpenACCDefaultClauseKind>( 1521db9f3b2SDimitry Andric Tok.getIdentifierInfo()->getName()) 1531db9f3b2SDimitry Andric .Case("none", OpenACCDefaultClauseKind::None) 1541db9f3b2SDimitry Andric .Case("present", OpenACCDefaultClauseKind::Present) 1551db9f3b2SDimitry Andric .Default(OpenACCDefaultClauseKind::Invalid); 1561db9f3b2SDimitry Andric } 1571db9f3b2SDimitry Andric 1585f757f3fSDimitry Andric enum class OpenACCSpecialTokenKind { 1595f757f3fSDimitry Andric ReadOnly, 1605f757f3fSDimitry Andric DevNum, 1615f757f3fSDimitry Andric Queues, 162*7a6dacacSDimitry Andric Zero, 163*7a6dacacSDimitry Andric Force, 164*7a6dacacSDimitry Andric Num, 165*7a6dacacSDimitry Andric Length, 1665f757f3fSDimitry Andric }; 1675f757f3fSDimitry Andric 1685f757f3fSDimitry Andric bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { 1695f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 1705f757f3fSDimitry Andric return false; 1715f757f3fSDimitry Andric 1725f757f3fSDimitry Andric switch (Kind) { 1735f757f3fSDimitry Andric case OpenACCSpecialTokenKind::ReadOnly: 1745f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("readonly"); 1755f757f3fSDimitry Andric case OpenACCSpecialTokenKind::DevNum: 1765f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("devnum"); 1775f757f3fSDimitry Andric case OpenACCSpecialTokenKind::Queues: 1785f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("queues"); 179*7a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Zero: 180*7a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("zero"); 181*7a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Force: 182*7a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("force"); 183*7a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Num: 184*7a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("num"); 185*7a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Length: 186*7a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("length"); 1875f757f3fSDimitry Andric } 1885f757f3fSDimitry Andric llvm_unreachable("Unknown 'Kind' Passed"); 1895f757f3fSDimitry Andric } 1905f757f3fSDimitry Andric 191*7a6dacacSDimitry Andric /// Used for cases where we have a token we want to check against an 192*7a6dacacSDimitry Andric /// 'identifier-like' token, but don't want to give awkward error messages in 193*7a6dacacSDimitry Andric /// cases where it is accidentially a keyword. 194*7a6dacacSDimitry Andric bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) { 195*7a6dacacSDimitry Andric if (Tok.is(tok::identifier)) 196*7a6dacacSDimitry Andric return true; 197*7a6dacacSDimitry Andric 198*7a6dacacSDimitry Andric if (!Tok.isAnnotation() && Tok.getIdentifierInfo() && 199*7a6dacacSDimitry Andric Tok.getIdentifierInfo()->isKeyword(P.getLangOpts())) 200*7a6dacacSDimitry Andric return true; 201*7a6dacacSDimitry Andric 202*7a6dacacSDimitry Andric return false; 203*7a6dacacSDimitry Andric } 204*7a6dacacSDimitry Andric 205*7a6dacacSDimitry Andric /// Parses and consumes an identifer followed immediately by a single colon, and 206*7a6dacacSDimitry Andric /// diagnoses if it is not the 'special token' kind that we require. Used when 207*7a6dacacSDimitry Andric /// the tag is the only valid value. 208*7a6dacacSDimitry Andric /// Return 'true' if the special token was matched, false if no special token, 209*7a6dacacSDimitry Andric /// or an invalid special token was found. 210*7a6dacacSDimitry Andric template <typename DirOrClauseTy> 211*7a6dacacSDimitry Andric bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind, 212*7a6dacacSDimitry Andric DirOrClauseTy DirOrClause) { 213*7a6dacacSDimitry Andric Token IdentTok = P.getCurToken(); 214*7a6dacacSDimitry Andric // If this is an identifier-like thing followed by ':', it is one of the 215*7a6dacacSDimitry Andric // OpenACC 'special' name tags, so consume it. 216*7a6dacacSDimitry Andric if (isTokenIdentifierOrKeyword(P, IdentTok) && P.NextToken().is(tok::colon)) { 217*7a6dacacSDimitry Andric P.ConsumeToken(); 218*7a6dacacSDimitry Andric P.ConsumeToken(); 219*7a6dacacSDimitry Andric 220*7a6dacacSDimitry Andric if (!isOpenACCSpecialToken(Kind, IdentTok)) { 221*7a6dacacSDimitry Andric P.Diag(IdentTok, diag::err_acc_invalid_tag_kind) 222*7a6dacacSDimitry Andric << IdentTok.getIdentifierInfo() << DirOrClause 223*7a6dacacSDimitry Andric << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>; 224*7a6dacacSDimitry Andric return false; 225*7a6dacacSDimitry Andric } 226*7a6dacacSDimitry Andric 227*7a6dacacSDimitry Andric return true; 228*7a6dacacSDimitry Andric } 229*7a6dacacSDimitry Andric 230*7a6dacacSDimitry Andric return false; 231*7a6dacacSDimitry Andric } 232*7a6dacacSDimitry Andric 2335f757f3fSDimitry Andric bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { 2345f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 2355f757f3fSDimitry Andric return false; 2365f757f3fSDimitry Andric 2375f757f3fSDimitry Andric switch (Kind) { 2385f757f3fSDimitry Andric case OpenACCDirectiveKind::Parallel: 2395f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("parallel"); 2405f757f3fSDimitry Andric case OpenACCDirectiveKind::Serial: 2415f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("serial"); 2425f757f3fSDimitry Andric case OpenACCDirectiveKind::Kernels: 2435f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("kernels"); 2445f757f3fSDimitry Andric case OpenACCDirectiveKind::Data: 2455f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("data"); 2465f757f3fSDimitry Andric case OpenACCDirectiveKind::HostData: 2475f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("host_data"); 2485f757f3fSDimitry Andric case OpenACCDirectiveKind::Loop: 2495f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("loop"); 2505f757f3fSDimitry Andric case OpenACCDirectiveKind::Cache: 2515f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("cache"); 2525f757f3fSDimitry Andric 2535f757f3fSDimitry Andric case OpenACCDirectiveKind::ParallelLoop: 2545f757f3fSDimitry Andric case OpenACCDirectiveKind::SerialLoop: 2555f757f3fSDimitry Andric case OpenACCDirectiveKind::KernelsLoop: 2565f757f3fSDimitry Andric case OpenACCDirectiveKind::EnterData: 2575f757f3fSDimitry Andric case OpenACCDirectiveKind::ExitData: 2585f757f3fSDimitry Andric return false; 2595f757f3fSDimitry Andric 2605f757f3fSDimitry Andric case OpenACCDirectiveKind::Atomic: 2615f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("atomic"); 2625f757f3fSDimitry Andric case OpenACCDirectiveKind::Routine: 2635f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("routine"); 2645f757f3fSDimitry Andric case OpenACCDirectiveKind::Declare: 2655f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("declare"); 2665f757f3fSDimitry Andric case OpenACCDirectiveKind::Init: 2675f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("init"); 2685f757f3fSDimitry Andric case OpenACCDirectiveKind::Shutdown: 2695f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("shutdown"); 2705f757f3fSDimitry Andric case OpenACCDirectiveKind::Set: 2715f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("set"); 2725f757f3fSDimitry Andric case OpenACCDirectiveKind::Update: 2735f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("update"); 2745f757f3fSDimitry Andric case OpenACCDirectiveKind::Wait: 2755f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("wait"); 2765f757f3fSDimitry Andric case OpenACCDirectiveKind::Invalid: 2775f757f3fSDimitry Andric return false; 2785f757f3fSDimitry Andric } 2795f757f3fSDimitry Andric llvm_unreachable("Unknown 'Kind' Passed"); 2805f757f3fSDimitry Andric } 2815f757f3fSDimitry Andric 282*7a6dacacSDimitry Andric OpenACCReductionOperator ParseReductionOperator(Parser &P) { 283*7a6dacacSDimitry Andric // If there is no colon, treat as if the reduction operator was missing, else 284*7a6dacacSDimitry Andric // we probably will not recover from it in the case where an expression starts 285*7a6dacacSDimitry Andric // with one of the operator tokens. 286*7a6dacacSDimitry Andric if (P.NextToken().isNot(tok::colon)) { 287*7a6dacacSDimitry Andric P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator); 288*7a6dacacSDimitry Andric return OpenACCReductionOperator::Invalid; 289*7a6dacacSDimitry Andric } 290*7a6dacacSDimitry Andric Token ReductionKindTok = P.getCurToken(); 291*7a6dacacSDimitry Andric // Consume both the kind and the colon. 292*7a6dacacSDimitry Andric P.ConsumeToken(); 293*7a6dacacSDimitry Andric P.ConsumeToken(); 294*7a6dacacSDimitry Andric 295*7a6dacacSDimitry Andric switch (ReductionKindTok.getKind()) { 296*7a6dacacSDimitry Andric case tok::plus: 297*7a6dacacSDimitry Andric return OpenACCReductionOperator::Addition; 298*7a6dacacSDimitry Andric case tok::star: 299*7a6dacacSDimitry Andric return OpenACCReductionOperator::Multiplication; 300*7a6dacacSDimitry Andric case tok::amp: 301*7a6dacacSDimitry Andric return OpenACCReductionOperator::BitwiseAnd; 302*7a6dacacSDimitry Andric case tok::pipe: 303*7a6dacacSDimitry Andric return OpenACCReductionOperator::BitwiseOr; 304*7a6dacacSDimitry Andric case tok::caret: 305*7a6dacacSDimitry Andric return OpenACCReductionOperator::BitwiseXOr; 306*7a6dacacSDimitry Andric case tok::ampamp: 307*7a6dacacSDimitry Andric return OpenACCReductionOperator::And; 308*7a6dacacSDimitry Andric case tok::pipepipe: 309*7a6dacacSDimitry Andric return OpenACCReductionOperator::Or; 310*7a6dacacSDimitry Andric case tok::identifier: 311*7a6dacacSDimitry Andric if (ReductionKindTok.getIdentifierInfo()->isStr("max")) 312*7a6dacacSDimitry Andric return OpenACCReductionOperator::Max; 313*7a6dacacSDimitry Andric if (ReductionKindTok.getIdentifierInfo()->isStr("min")) 314*7a6dacacSDimitry Andric return OpenACCReductionOperator::Min; 315*7a6dacacSDimitry Andric LLVM_FALLTHROUGH; 316*7a6dacacSDimitry Andric default: 317*7a6dacacSDimitry Andric P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator); 318*7a6dacacSDimitry Andric return OpenACCReductionOperator::Invalid; 319*7a6dacacSDimitry Andric } 320*7a6dacacSDimitry Andric llvm_unreachable("Reduction op token kind not caught by 'default'?"); 321*7a6dacacSDimitry Andric } 322*7a6dacacSDimitry Andric 3231db9f3b2SDimitry Andric /// Used for cases where we expect an identifier-like token, but don't want to 3241db9f3b2SDimitry Andric /// give awkward error messages in cases where it is accidentially a keyword. 3251db9f3b2SDimitry Andric bool expectIdentifierOrKeyword(Parser &P) { 3261db9f3b2SDimitry Andric Token Tok = P.getCurToken(); 3271db9f3b2SDimitry Andric 328*7a6dacacSDimitry Andric if (isTokenIdentifierOrKeyword(P, Tok)) 3291db9f3b2SDimitry Andric return false; 3301db9f3b2SDimitry Andric 3311db9f3b2SDimitry Andric P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; 3321db9f3b2SDimitry Andric return true; 3331db9f3b2SDimitry Andric } 3341db9f3b2SDimitry Andric 3355f757f3fSDimitry Andric OpenACCDirectiveKind 3365f757f3fSDimitry Andric ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, 3375f757f3fSDimitry Andric OpenACCDirectiveKindEx ExtDirKind) { 3385f757f3fSDimitry Andric Token SecondTok = P.getCurToken(); 3395f757f3fSDimitry Andric 3405f757f3fSDimitry Andric if (SecondTok.isAnnotation()) { 3415f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 3425f757f3fSDimitry Andric << 0 << FirstTok.getIdentifierInfo(); 3435f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 3445f757f3fSDimitry Andric } 3455f757f3fSDimitry Andric 346cb14a3feSDimitry Andric // Consume the second name anyway, this way we can continue on without making 347cb14a3feSDimitry Andric // this oddly look like a clause. 348cb14a3feSDimitry Andric P.ConsumeAnyToken(); 349cb14a3feSDimitry Andric 3505f757f3fSDimitry Andric if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { 3515f757f3fSDimitry Andric if (!SecondTok.is(tok::identifier)) 3525f757f3fSDimitry Andric P.Diag(SecondTok, diag::err_expected) << tok::identifier; 3535f757f3fSDimitry Andric else 3545f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 3555f757f3fSDimitry Andric << 1 << FirstTok.getIdentifierInfo()->getName() 3565f757f3fSDimitry Andric << SecondTok.getIdentifierInfo()->getName(); 3575f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 3585f757f3fSDimitry Andric } 3595f757f3fSDimitry Andric 3605f757f3fSDimitry Andric return ExtDirKind == OpenACCDirectiveKindEx::Enter 3615f757f3fSDimitry Andric ? OpenACCDirectiveKind::EnterData 3625f757f3fSDimitry Andric : OpenACCDirectiveKind::ExitData; 3635f757f3fSDimitry Andric } 3645f757f3fSDimitry Andric 3655f757f3fSDimitry Andric OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) { 3665f757f3fSDimitry Andric Token AtomicClauseToken = P.getCurToken(); 3675f757f3fSDimitry Andric 3685f757f3fSDimitry Andric // #pragma acc atomic is equivilent to update: 3695f757f3fSDimitry Andric if (AtomicClauseToken.isAnnotation()) 3705f757f3fSDimitry Andric return OpenACCAtomicKind::Update; 3715f757f3fSDimitry Andric 3725f757f3fSDimitry Andric OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken); 3735f757f3fSDimitry Andric 3745f757f3fSDimitry Andric // If we don't know what this is, treat it as 'nothing', and treat the rest of 3755f757f3fSDimitry Andric // this as a clause list, which, despite being invalid, is likely what the 3765f757f3fSDimitry Andric // user was trying to do. 3775f757f3fSDimitry Andric if (AtomicKind == OpenACCAtomicKind::Invalid) 3785f757f3fSDimitry Andric return OpenACCAtomicKind::Update; 3795f757f3fSDimitry Andric 3805f757f3fSDimitry Andric P.ConsumeToken(); 3815f757f3fSDimitry Andric return AtomicKind; 3825f757f3fSDimitry Andric } 3835f757f3fSDimitry Andric 3845f757f3fSDimitry Andric // Parse and consume the tokens for OpenACC Directive/Construct kinds. 3855f757f3fSDimitry Andric OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { 3865f757f3fSDimitry Andric Token FirstTok = P.getCurToken(); 3875f757f3fSDimitry Andric 3885f757f3fSDimitry Andric // Just #pragma acc can get us immediately to the end, make sure we don't 3895f757f3fSDimitry Andric // introspect on the spelling before then. 3905f757f3fSDimitry Andric if (FirstTok.isNot(tok::identifier)) { 3915f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_missing_directive); 392cb14a3feSDimitry Andric 393cb14a3feSDimitry Andric if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 394cb14a3feSDimitry Andric P.ConsumeAnyToken(); 395cb14a3feSDimitry Andric 3965f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 3975f757f3fSDimitry Andric } 3985f757f3fSDimitry Andric 3995f757f3fSDimitry Andric P.ConsumeToken(); 4005f757f3fSDimitry Andric 4015f757f3fSDimitry Andric OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok); 4025f757f3fSDimitry Andric 4035f757f3fSDimitry Andric // OpenACCDirectiveKindEx is meant to be an extended list 4045f757f3fSDimitry Andric // over OpenACCDirectiveKind, so any value below Invalid is one of the 4055f757f3fSDimitry Andric // OpenACCDirectiveKind values. This switch takes care of all of the extra 4065f757f3fSDimitry Andric // parsing required for the Extended values. At the end of this block, 4075f757f3fSDimitry Andric // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can 4085f757f3fSDimitry Andric // immediately cast it and use it as that. 4095f757f3fSDimitry Andric if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) { 4105f757f3fSDimitry Andric switch (ExDirKind) { 4115f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Invalid: { 4125f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 4135f757f3fSDimitry Andric << 0 << FirstTok.getIdentifierInfo(); 4145f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 4155f757f3fSDimitry Andric } 4165f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Enter: 4175f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Exit: 4185f757f3fSDimitry Andric return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind); 4195f757f3fSDimitry Andric } 4205f757f3fSDimitry Andric } 4215f757f3fSDimitry Andric 4225f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind); 4235f757f3fSDimitry Andric 4245f757f3fSDimitry Andric // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any 4255f757f3fSDimitry Andric // other attempt at a combined construct will be diagnosed as an invalid 4265f757f3fSDimitry Andric // clause. 4275f757f3fSDimitry Andric Token SecondTok = P.getCurToken(); 4285f757f3fSDimitry Andric if (!SecondTok.isAnnotation() && 4295f757f3fSDimitry Andric isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) { 4305f757f3fSDimitry Andric switch (DirKind) { 4315f757f3fSDimitry Andric default: 4325f757f3fSDimitry Andric // Nothing to do except in the below cases, as they should be diagnosed as 4335f757f3fSDimitry Andric // a clause. 4345f757f3fSDimitry Andric break; 4355f757f3fSDimitry Andric case OpenACCDirectiveKind::Parallel: 4365f757f3fSDimitry Andric P.ConsumeToken(); 4375f757f3fSDimitry Andric return OpenACCDirectiveKind::ParallelLoop; 4385f757f3fSDimitry Andric case OpenACCDirectiveKind::Serial: 4395f757f3fSDimitry Andric P.ConsumeToken(); 4405f757f3fSDimitry Andric return OpenACCDirectiveKind::SerialLoop; 4415f757f3fSDimitry Andric case OpenACCDirectiveKind::Kernels: 4425f757f3fSDimitry Andric P.ConsumeToken(); 4435f757f3fSDimitry Andric return OpenACCDirectiveKind::KernelsLoop; 4445f757f3fSDimitry Andric } 4455f757f3fSDimitry Andric } 4465f757f3fSDimitry Andric 4475f757f3fSDimitry Andric return DirKind; 4485f757f3fSDimitry Andric } 4495f757f3fSDimitry Andric 450*7a6dacacSDimitry Andric enum ClauseParensKind { 451*7a6dacacSDimitry Andric None, 452*7a6dacacSDimitry Andric Optional, 453*7a6dacacSDimitry Andric Required 454*7a6dacacSDimitry Andric }; 455*7a6dacacSDimitry Andric 456*7a6dacacSDimitry Andric ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind, 457*7a6dacacSDimitry Andric OpenACCClauseKind Kind) { 458*7a6dacacSDimitry Andric switch (Kind) { 459*7a6dacacSDimitry Andric case OpenACCClauseKind::Self: 460*7a6dacacSDimitry Andric return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required 461*7a6dacacSDimitry Andric : ClauseParensKind::Optional; 462*7a6dacacSDimitry Andric case OpenACCClauseKind::Worker: 463*7a6dacacSDimitry Andric case OpenACCClauseKind::Vector: 464*7a6dacacSDimitry Andric return ClauseParensKind::Optional; 465*7a6dacacSDimitry Andric 466*7a6dacacSDimitry Andric case OpenACCClauseKind::Default: 467*7a6dacacSDimitry Andric case OpenACCClauseKind::If: 468*7a6dacacSDimitry Andric case OpenACCClauseKind::Create: 469*7a6dacacSDimitry Andric case OpenACCClauseKind::Copy: 470*7a6dacacSDimitry Andric case OpenACCClauseKind::CopyIn: 471*7a6dacacSDimitry Andric case OpenACCClauseKind::CopyOut: 472*7a6dacacSDimitry Andric case OpenACCClauseKind::UseDevice: 473*7a6dacacSDimitry Andric case OpenACCClauseKind::NoCreate: 474*7a6dacacSDimitry Andric case OpenACCClauseKind::Present: 475*7a6dacacSDimitry Andric case OpenACCClauseKind::DevicePtr: 476*7a6dacacSDimitry Andric case OpenACCClauseKind::Attach: 477*7a6dacacSDimitry Andric case OpenACCClauseKind::Detach: 478*7a6dacacSDimitry Andric case OpenACCClauseKind::Private: 479*7a6dacacSDimitry Andric case OpenACCClauseKind::FirstPrivate: 480*7a6dacacSDimitry Andric case OpenACCClauseKind::Delete: 481*7a6dacacSDimitry Andric case OpenACCClauseKind::DeviceResident: 482*7a6dacacSDimitry Andric case OpenACCClauseKind::Device: 483*7a6dacacSDimitry Andric case OpenACCClauseKind::Link: 484*7a6dacacSDimitry Andric case OpenACCClauseKind::Host: 485*7a6dacacSDimitry Andric case OpenACCClauseKind::Reduction: 486*7a6dacacSDimitry Andric case OpenACCClauseKind::Collapse: 487*7a6dacacSDimitry Andric case OpenACCClauseKind::Bind: 488*7a6dacacSDimitry Andric case OpenACCClauseKind::VectorLength: 489*7a6dacacSDimitry Andric case OpenACCClauseKind::NumGangs: 490*7a6dacacSDimitry Andric case OpenACCClauseKind::NumWorkers: 491*7a6dacacSDimitry Andric case OpenACCClauseKind::DeviceNum: 492*7a6dacacSDimitry Andric case OpenACCClauseKind::DefaultAsync: 493*7a6dacacSDimitry Andric case OpenACCClauseKind::DeviceType: 494*7a6dacacSDimitry Andric case OpenACCClauseKind::DType: 495*7a6dacacSDimitry Andric return ClauseParensKind::Required; 496*7a6dacacSDimitry Andric 497*7a6dacacSDimitry Andric case OpenACCClauseKind::Auto: 498*7a6dacacSDimitry Andric case OpenACCClauseKind::Finalize: 499*7a6dacacSDimitry Andric case OpenACCClauseKind::IfPresent: 500*7a6dacacSDimitry Andric case OpenACCClauseKind::Independent: 501*7a6dacacSDimitry Andric case OpenACCClauseKind::Invalid: 502*7a6dacacSDimitry Andric case OpenACCClauseKind::NoHost: 503*7a6dacacSDimitry Andric case OpenACCClauseKind::Seq: 504*7a6dacacSDimitry Andric return ClauseParensKind::None; 505*7a6dacacSDimitry Andric } 506*7a6dacacSDimitry Andric llvm_unreachable("Unhandled clause kind"); 5071db9f3b2SDimitry Andric } 5081db9f3b2SDimitry Andric 509*7a6dacacSDimitry Andric bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind, 510*7a6dacacSDimitry Andric OpenACCClauseKind Kind) { 511*7a6dacacSDimitry Andric return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional; 512*7a6dacacSDimitry Andric } 513*7a6dacacSDimitry Andric 514*7a6dacacSDimitry Andric bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind, 515*7a6dacacSDimitry Andric OpenACCClauseKind Kind) { 516*7a6dacacSDimitry Andric return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required; 5171db9f3b2SDimitry Andric } 5181db9f3b2SDimitry Andric 5191db9f3b2SDimitry Andric ExprResult ParseOpenACCConditionalExpr(Parser &P) { 5201db9f3b2SDimitry Andric // FIXME: It isn't clear if the spec saying 'condition' means the same as 5211db9f3b2SDimitry Andric // it does in an if/while/etc (See ParseCXXCondition), however as it was 5221db9f3b2SDimitry Andric // written with Fortran/C in mind, we're going to assume it just means an 5231db9f3b2SDimitry Andric // 'expression evaluating to boolean'. 5241db9f3b2SDimitry Andric return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression()); 5251db9f3b2SDimitry Andric } 5261db9f3b2SDimitry Andric 527cb14a3feSDimitry Andric // Skip until we see the end of pragma token, but don't consume it. This is us 528cb14a3feSDimitry Andric // just giving up on the rest of the pragma so we can continue executing. We 529cb14a3feSDimitry Andric // have to do this because 'SkipUntil' considers paren balancing, which isn't 530cb14a3feSDimitry Andric // what we want. 531cb14a3feSDimitry Andric void SkipUntilEndOfDirective(Parser &P) { 532cb14a3feSDimitry Andric while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 533cb14a3feSDimitry Andric P.ConsumeAnyToken(); 534cb14a3feSDimitry Andric } 535cb14a3feSDimitry Andric 536*7a6dacacSDimitry Andric } // namespace 537*7a6dacacSDimitry Andric 538cb14a3feSDimitry Andric // OpenACC 3.3, section 1.7: 539cb14a3feSDimitry Andric // To simplify the specification and convey appropriate constraint information, 540cb14a3feSDimitry Andric // a pqr-list is a comma-separated list of pdr items. The one exception is a 541cb14a3feSDimitry Andric // clause-list, which is a list of one or more clauses optionally separated by 542cb14a3feSDimitry Andric // commas. 543*7a6dacacSDimitry Andric void Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { 544cb14a3feSDimitry Andric bool FirstClause = true; 545*7a6dacacSDimitry Andric while (getCurToken().isNot(tok::annot_pragma_openacc_end)) { 546cb14a3feSDimitry Andric // Comma is optional in a clause-list. 547*7a6dacacSDimitry Andric if (!FirstClause && getCurToken().is(tok::comma)) 548*7a6dacacSDimitry Andric ConsumeToken(); 549cb14a3feSDimitry Andric FirstClause = false; 550cb14a3feSDimitry Andric 551cb14a3feSDimitry Andric // Recovering from a bad clause is really difficult, so we just give up on 552cb14a3feSDimitry Andric // error. 553*7a6dacacSDimitry Andric if (ParseOpenACCClause(DirKind)) { 554*7a6dacacSDimitry Andric SkipUntilEndOfDirective(*this); 555cb14a3feSDimitry Andric return; 556cb14a3feSDimitry Andric } 557cb14a3feSDimitry Andric } 5585f757f3fSDimitry Andric } 5595f757f3fSDimitry Andric 560*7a6dacacSDimitry Andric ExprResult Parser::ParseOpenACCIntExpr() { 561*7a6dacacSDimitry Andric // FIXME: this is required to be an integer expression (or dependent), so we 562*7a6dacacSDimitry Andric // should ensure that is the case by passing this to SEMA here. 563*7a6dacacSDimitry Andric return getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 564*7a6dacacSDimitry Andric } 565*7a6dacacSDimitry Andric 566*7a6dacacSDimitry Andric bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) { 567*7a6dacacSDimitry Andric // FIXME: Future clauses will require 'special word' parsing, check for one, 568*7a6dacacSDimitry Andric // then parse it based on whether it is a clause that requires a 'special 569*7a6dacacSDimitry Andric // word'. 570*7a6dacacSDimitry Andric (void)Kind; 571*7a6dacacSDimitry Andric 572*7a6dacacSDimitry Andric // If the var parsing fails, skip until the end of the directive as this is 573*7a6dacacSDimitry Andric // an expression and gets messy if we try to continue otherwise. 574*7a6dacacSDimitry Andric if (ParseOpenACCVar()) 575*7a6dacacSDimitry Andric return true; 576*7a6dacacSDimitry Andric 577*7a6dacacSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 578*7a6dacacSDimitry Andric ExpectAndConsume(tok::comma); 579*7a6dacacSDimitry Andric 580*7a6dacacSDimitry Andric // If the var parsing fails, skip until the end of the directive as this is 581*7a6dacacSDimitry Andric // an expression and gets messy if we try to continue otherwise. 582*7a6dacacSDimitry Andric if (ParseOpenACCVar()) 583*7a6dacacSDimitry Andric return true; 584*7a6dacacSDimitry Andric } 585*7a6dacacSDimitry Andric return false; 586*7a6dacacSDimitry Andric } 587*7a6dacacSDimitry Andric 588*7a6dacacSDimitry Andric /// OpenACC 3.3 Section 2.4: 589*7a6dacacSDimitry Andric /// The argument to the device_type clause is a comma-separated list of one or 590*7a6dacacSDimitry Andric /// more device architecture name identifiers, or an asterisk. 591*7a6dacacSDimitry Andric /// 592*7a6dacacSDimitry Andric /// The syntax of the device_type clause is 593*7a6dacacSDimitry Andric /// device_type( * ) 594*7a6dacacSDimitry Andric /// device_type( device-type-list ) 595*7a6dacacSDimitry Andric /// 596*7a6dacacSDimitry Andric /// The device_type clause may be abbreviated to dtype. 597*7a6dacacSDimitry Andric bool Parser::ParseOpenACCDeviceTypeList() { 598*7a6dacacSDimitry Andric 599*7a6dacacSDimitry Andric if (expectIdentifierOrKeyword(*this)) { 600*7a6dacacSDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 601*7a6dacacSDimitry Andric Parser::StopBeforeMatch); 602*7a6dacacSDimitry Andric return false; 603*7a6dacacSDimitry Andric } 604*7a6dacacSDimitry Andric ConsumeToken(); 605*7a6dacacSDimitry Andric 606*7a6dacacSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 607*7a6dacacSDimitry Andric ExpectAndConsume(tok::comma); 608*7a6dacacSDimitry Andric 609*7a6dacacSDimitry Andric if (expectIdentifierOrKeyword(*this)) { 610*7a6dacacSDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 611*7a6dacacSDimitry Andric Parser::StopBeforeMatch); 612*7a6dacacSDimitry Andric return false; 613*7a6dacacSDimitry Andric } 614*7a6dacacSDimitry Andric ConsumeToken(); 615*7a6dacacSDimitry Andric } 616*7a6dacacSDimitry Andric return false; 617*7a6dacacSDimitry Andric } 618*7a6dacacSDimitry Andric 619*7a6dacacSDimitry Andric // The OpenACC Clause List is a comma or space-delimited list of clauses (see 620*7a6dacacSDimitry Andric // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't 621*7a6dacacSDimitry Andric // really have its owner grammar and each individual one has its own definition. 622*7a6dacacSDimitry Andric // However, they all are named with a single-identifier (or auto/default!) 623*7a6dacacSDimitry Andric // token, followed in some cases by either braces or parens. 624*7a6dacacSDimitry Andric bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) { 625*7a6dacacSDimitry Andric // A number of clause names are actually keywords, so accept a keyword that 626*7a6dacacSDimitry Andric // can be converted to a name. 627*7a6dacacSDimitry Andric if (expectIdentifierOrKeyword(*this)) 628*7a6dacacSDimitry Andric return true; 629*7a6dacacSDimitry Andric 630*7a6dacacSDimitry Andric OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken()); 631*7a6dacacSDimitry Andric 632*7a6dacacSDimitry Andric if (Kind == OpenACCClauseKind::Invalid) 633*7a6dacacSDimitry Andric return Diag(getCurToken(), diag::err_acc_invalid_clause) 634*7a6dacacSDimitry Andric << getCurToken().getIdentifierInfo(); 635*7a6dacacSDimitry Andric 636*7a6dacacSDimitry Andric // Consume the clause name. 637*7a6dacacSDimitry Andric ConsumeToken(); 638*7a6dacacSDimitry Andric 639*7a6dacacSDimitry Andric return ParseOpenACCClauseParams(DirKind, Kind); 640*7a6dacacSDimitry Andric } 641*7a6dacacSDimitry Andric 642*7a6dacacSDimitry Andric bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind, 643*7a6dacacSDimitry Andric OpenACCClauseKind Kind) { 644*7a6dacacSDimitry Andric BalancedDelimiterTracker Parens(*this, tok::l_paren, 645*7a6dacacSDimitry Andric tok::annot_pragma_openacc_end); 646*7a6dacacSDimitry Andric 647*7a6dacacSDimitry Andric if (ClauseHasRequiredParens(DirKind, Kind)) { 648*7a6dacacSDimitry Andric if (Parens.expectAndConsume()) { 649*7a6dacacSDimitry Andric // We are missing a paren, so assume that the person just forgot the 650*7a6dacacSDimitry Andric // parameter. Return 'false' so we try to continue on and parse the next 651*7a6dacacSDimitry Andric // clause. 652*7a6dacacSDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, 653*7a6dacacSDimitry Andric Parser::StopBeforeMatch); 654*7a6dacacSDimitry Andric return false; 655*7a6dacacSDimitry Andric } 656*7a6dacacSDimitry Andric 657*7a6dacacSDimitry Andric switch (Kind) { 658*7a6dacacSDimitry Andric case OpenACCClauseKind::Default: { 659*7a6dacacSDimitry Andric Token DefKindTok = getCurToken(); 660*7a6dacacSDimitry Andric 661*7a6dacacSDimitry Andric if (expectIdentifierOrKeyword(*this)) 662*7a6dacacSDimitry Andric break; 663*7a6dacacSDimitry Andric 664*7a6dacacSDimitry Andric ConsumeToken(); 665*7a6dacacSDimitry Andric 666*7a6dacacSDimitry Andric if (getOpenACCDefaultClauseKind(DefKindTok) == 667*7a6dacacSDimitry Andric OpenACCDefaultClauseKind::Invalid) 668*7a6dacacSDimitry Andric Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); 669*7a6dacacSDimitry Andric 670*7a6dacacSDimitry Andric break; 671*7a6dacacSDimitry Andric } 672*7a6dacacSDimitry Andric case OpenACCClauseKind::If: { 673*7a6dacacSDimitry Andric ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); 674*7a6dacacSDimitry Andric // An invalid expression can be just about anything, so just give up on 675*7a6dacacSDimitry Andric // this clause list. 676*7a6dacacSDimitry Andric if (CondExpr.isInvalid()) 677*7a6dacacSDimitry Andric return true; 678*7a6dacacSDimitry Andric break; 679*7a6dacacSDimitry Andric } 680*7a6dacacSDimitry Andric case OpenACCClauseKind::CopyIn: 681*7a6dacacSDimitry Andric tryParseAndConsumeSpecialTokenKind( 682*7a6dacacSDimitry Andric *this, OpenACCSpecialTokenKind::ReadOnly, Kind); 683*7a6dacacSDimitry Andric if (ParseOpenACCClauseVarList(Kind)) 684*7a6dacacSDimitry Andric return true; 685*7a6dacacSDimitry Andric break; 686*7a6dacacSDimitry Andric case OpenACCClauseKind::Create: 687*7a6dacacSDimitry Andric case OpenACCClauseKind::CopyOut: 688*7a6dacacSDimitry Andric tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Zero, 689*7a6dacacSDimitry Andric Kind); 690*7a6dacacSDimitry Andric if (ParseOpenACCClauseVarList(Kind)) 691*7a6dacacSDimitry Andric return true; 692*7a6dacacSDimitry Andric break; 693*7a6dacacSDimitry Andric case OpenACCClauseKind::Reduction: 694*7a6dacacSDimitry Andric // If we're missing a clause-kind (or it is invalid), see if we can parse 695*7a6dacacSDimitry Andric // the var-list anyway. 696*7a6dacacSDimitry Andric ParseReductionOperator(*this); 697*7a6dacacSDimitry Andric if (ParseOpenACCClauseVarList(Kind)) 698*7a6dacacSDimitry Andric return true; 699*7a6dacacSDimitry Andric break; 700*7a6dacacSDimitry Andric case OpenACCClauseKind::Self: 701*7a6dacacSDimitry Andric // The 'self' clause is a var-list instead of a 'condition' in the case of 702*7a6dacacSDimitry Andric // the 'update' clause, so we have to handle it here. U se an assert to 703*7a6dacacSDimitry Andric // make sure we get the right differentiator. 704*7a6dacacSDimitry Andric assert(DirKind == OpenACCDirectiveKind::Update); 705*7a6dacacSDimitry Andric LLVM_FALLTHROUGH; 706*7a6dacacSDimitry Andric case OpenACCClauseKind::Attach: 707*7a6dacacSDimitry Andric case OpenACCClauseKind::Copy: 708*7a6dacacSDimitry Andric case OpenACCClauseKind::Delete: 709*7a6dacacSDimitry Andric case OpenACCClauseKind::Detach: 710*7a6dacacSDimitry Andric case OpenACCClauseKind::Device: 711*7a6dacacSDimitry Andric case OpenACCClauseKind::DeviceResident: 712*7a6dacacSDimitry Andric case OpenACCClauseKind::DevicePtr: 713*7a6dacacSDimitry Andric case OpenACCClauseKind::FirstPrivate: 714*7a6dacacSDimitry Andric case OpenACCClauseKind::Host: 715*7a6dacacSDimitry Andric case OpenACCClauseKind::Link: 716*7a6dacacSDimitry Andric case OpenACCClauseKind::NoCreate: 717*7a6dacacSDimitry Andric case OpenACCClauseKind::Present: 718*7a6dacacSDimitry Andric case OpenACCClauseKind::Private: 719*7a6dacacSDimitry Andric case OpenACCClauseKind::UseDevice: 720*7a6dacacSDimitry Andric if (ParseOpenACCClauseVarList(Kind)) 721*7a6dacacSDimitry Andric return true; 722*7a6dacacSDimitry Andric break; 723*7a6dacacSDimitry Andric case OpenACCClauseKind::Collapse: { 724*7a6dacacSDimitry Andric tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Force, 725*7a6dacacSDimitry Andric Kind); 726*7a6dacacSDimitry Andric ExprResult NumLoops = 727*7a6dacacSDimitry Andric getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 728*7a6dacacSDimitry Andric if (NumLoops.isInvalid()) 729*7a6dacacSDimitry Andric return true; 730*7a6dacacSDimitry Andric break; 731*7a6dacacSDimitry Andric } 732*7a6dacacSDimitry Andric case OpenACCClauseKind::Bind: { 733*7a6dacacSDimitry Andric ExprResult BindArg = ParseOpenACCBindClauseArgument(); 734*7a6dacacSDimitry Andric if (BindArg.isInvalid()) 735*7a6dacacSDimitry Andric return true; 736*7a6dacacSDimitry Andric break; 737*7a6dacacSDimitry Andric } 738*7a6dacacSDimitry Andric case OpenACCClauseKind::NumGangs: 739*7a6dacacSDimitry Andric case OpenACCClauseKind::NumWorkers: 740*7a6dacacSDimitry Andric case OpenACCClauseKind::DeviceNum: 741*7a6dacacSDimitry Andric case OpenACCClauseKind::DefaultAsync: 742*7a6dacacSDimitry Andric case OpenACCClauseKind::VectorLength: { 743*7a6dacacSDimitry Andric ExprResult IntExpr = ParseOpenACCIntExpr(); 744*7a6dacacSDimitry Andric if (IntExpr.isInvalid()) 745*7a6dacacSDimitry Andric return true; 746*7a6dacacSDimitry Andric break; 747*7a6dacacSDimitry Andric } 748*7a6dacacSDimitry Andric case OpenACCClauseKind::DType: 749*7a6dacacSDimitry Andric case OpenACCClauseKind::DeviceType: 750*7a6dacacSDimitry Andric if (getCurToken().is(tok::star)) { 751*7a6dacacSDimitry Andric // FIXME: We want to mark that this is an 'everything else' type of 752*7a6dacacSDimitry Andric // device_type in Sema. 753*7a6dacacSDimitry Andric ConsumeToken(); 754*7a6dacacSDimitry Andric } else if (ParseOpenACCDeviceTypeList()) { 755*7a6dacacSDimitry Andric return true; 756*7a6dacacSDimitry Andric } 757*7a6dacacSDimitry Andric break; 758*7a6dacacSDimitry Andric default: 759*7a6dacacSDimitry Andric llvm_unreachable("Not a required parens type?"); 760*7a6dacacSDimitry Andric } 761*7a6dacacSDimitry Andric 762*7a6dacacSDimitry Andric return Parens.consumeClose(); 763*7a6dacacSDimitry Andric } else if (ClauseHasOptionalParens(DirKind, Kind)) { 764*7a6dacacSDimitry Andric if (!Parens.consumeOpen()) { 765*7a6dacacSDimitry Andric switch (Kind) { 766*7a6dacacSDimitry Andric case OpenACCClauseKind::Self: { 767*7a6dacacSDimitry Andric assert(DirKind != OpenACCDirectiveKind::Update); 768*7a6dacacSDimitry Andric ExprResult CondExpr = ParseOpenACCConditionalExpr(*this); 769*7a6dacacSDimitry Andric // An invalid expression can be just about anything, so just give up on 770*7a6dacacSDimitry Andric // this clause list. 771*7a6dacacSDimitry Andric if (CondExpr.isInvalid()) 772*7a6dacacSDimitry Andric return true; 773*7a6dacacSDimitry Andric break; 774*7a6dacacSDimitry Andric } 775*7a6dacacSDimitry Andric case OpenACCClauseKind::Vector: 776*7a6dacacSDimitry Andric case OpenACCClauseKind::Worker: { 777*7a6dacacSDimitry Andric tryParseAndConsumeSpecialTokenKind(*this, 778*7a6dacacSDimitry Andric Kind == OpenACCClauseKind::Vector 779*7a6dacacSDimitry Andric ? OpenACCSpecialTokenKind::Length 780*7a6dacacSDimitry Andric : OpenACCSpecialTokenKind::Num, 781*7a6dacacSDimitry Andric Kind); 782*7a6dacacSDimitry Andric ExprResult IntExpr = ParseOpenACCIntExpr(); 783*7a6dacacSDimitry Andric if (IntExpr.isInvalid()) 784*7a6dacacSDimitry Andric return true; 785*7a6dacacSDimitry Andric break; 786*7a6dacacSDimitry Andric } 787*7a6dacacSDimitry Andric default: 788*7a6dacacSDimitry Andric llvm_unreachable("Not an optional parens type?"); 789*7a6dacacSDimitry Andric } 790*7a6dacacSDimitry Andric Parens.consumeClose(); 791*7a6dacacSDimitry Andric } 792*7a6dacacSDimitry Andric } 793*7a6dacacSDimitry Andric return false; 794*7a6dacacSDimitry Andric } 7955f757f3fSDimitry Andric 7965f757f3fSDimitry Andric /// OpenACC 3.3, section 2.16: 7975f757f3fSDimitry Andric /// In this section and throughout the specification, the term wait-argument 7985f757f3fSDimitry Andric /// means: 7995f757f3fSDimitry Andric /// [ devnum : int-expr : ] [ queues : ] async-argument-list 8005f757f3fSDimitry Andric bool Parser::ParseOpenACCWaitArgument() { 8015f757f3fSDimitry Andric // [devnum : int-expr : ] 8025f757f3fSDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && 8035f757f3fSDimitry Andric NextToken().is(tok::colon)) { 8045f757f3fSDimitry Andric // Consume devnum. 8055f757f3fSDimitry Andric ConsumeToken(); 8065f757f3fSDimitry Andric // Consume colon. 8075f757f3fSDimitry Andric ConsumeToken(); 8085f757f3fSDimitry Andric 8095f757f3fSDimitry Andric ExprResult IntExpr = 8105f757f3fSDimitry Andric getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 8115f757f3fSDimitry Andric if (IntExpr.isInvalid()) 8125f757f3fSDimitry Andric return true; 8135f757f3fSDimitry Andric 8145f757f3fSDimitry Andric if (ExpectAndConsume(tok::colon)) 8155f757f3fSDimitry Andric return true; 8165f757f3fSDimitry Andric } 8175f757f3fSDimitry Andric 8185f757f3fSDimitry Andric // [ queues : ] 8195f757f3fSDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && 8205f757f3fSDimitry Andric NextToken().is(tok::colon)) { 8215f757f3fSDimitry Andric // Consume queues. 8225f757f3fSDimitry Andric ConsumeToken(); 8235f757f3fSDimitry Andric // Consume colon. 8245f757f3fSDimitry Andric ConsumeToken(); 8255f757f3fSDimitry Andric } 8265f757f3fSDimitry Andric 8275f757f3fSDimitry Andric // OpenACC 3.3, section 2.16: 8285f757f3fSDimitry Andric // the term 'async-argument' means a nonnegative scalar integer expression, or 8295f757f3fSDimitry Andric // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined 8305f757f3fSDimitry Andric // in the C header file and the Fortran opacc module. 8315f757f3fSDimitry Andric // 8325f757f3fSDimitry Andric // We are parsing this simply as list of assignment expressions (to avoid 8335f757f3fSDimitry Andric // comma being troublesome), and will ensure it is an integral type. The 8345f757f3fSDimitry Andric // 'special' types are defined as macros, so we can't really check those 8355f757f3fSDimitry Andric // (other than perhaps as values at one point?), but the standard does say it 8365f757f3fSDimitry Andric // is implementation-defined to use any other negative value. 8375f757f3fSDimitry Andric // 8385f757f3fSDimitry Andric // 8395f757f3fSDimitry Andric bool FirstArg = true; 8405f757f3fSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 8415f757f3fSDimitry Andric if (!FirstArg) { 8425f757f3fSDimitry Andric if (ExpectAndConsume(tok::comma)) 8435f757f3fSDimitry Andric return true; 8445f757f3fSDimitry Andric } 8455f757f3fSDimitry Andric FirstArg = false; 8465f757f3fSDimitry Andric 8475f757f3fSDimitry Andric ExprResult CurArg = 8485f757f3fSDimitry Andric getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 8495f757f3fSDimitry Andric 8505f757f3fSDimitry Andric if (CurArg.isInvalid()) 8515f757f3fSDimitry Andric return true; 8525f757f3fSDimitry Andric } 8535f757f3fSDimitry Andric 8545f757f3fSDimitry Andric return false; 8555f757f3fSDimitry Andric } 8565f757f3fSDimitry Andric 8575f757f3fSDimitry Andric ExprResult Parser::ParseOpenACCIDExpression() { 8585f757f3fSDimitry Andric ExprResult Res; 8595f757f3fSDimitry Andric if (getLangOpts().CPlusPlus) { 860*7a6dacacSDimitry Andric Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true); 8615f757f3fSDimitry Andric } else { 8625f757f3fSDimitry Andric // There isn't anything quite the same as ParseCXXIdExpression for C, so we 8635f757f3fSDimitry Andric // need to get the identifier, then call into Sema ourselves. 8645f757f3fSDimitry Andric 8655f757f3fSDimitry Andric if (Tok.isNot(tok::identifier)) { 8665f757f3fSDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier; 8675f757f3fSDimitry Andric return ExprError(); 8685f757f3fSDimitry Andric } 8695f757f3fSDimitry Andric 8705f757f3fSDimitry Andric Token FuncName = getCurToken(); 8715f757f3fSDimitry Andric UnqualifiedId Name; 8725f757f3fSDimitry Andric CXXScopeSpec ScopeSpec; 8735f757f3fSDimitry Andric SourceLocation TemplateKWLoc; 8745f757f3fSDimitry Andric Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken()); 8755f757f3fSDimitry Andric 8765f757f3fSDimitry Andric // Ensure this is a valid identifier. We don't accept causing implicit 8775f757f3fSDimitry Andric // function declarations per the spec, so always claim to not have trailing 8785f757f3fSDimitry Andric // L Paren. 8795f757f3fSDimitry Andric Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, 8805f757f3fSDimitry Andric Name, /*HasTrailingLParen=*/false, 8815f757f3fSDimitry Andric /*isAddressOfOperand=*/false); 8825f757f3fSDimitry Andric } 8835f757f3fSDimitry Andric 8845f757f3fSDimitry Andric return getActions().CorrectDelayedTyposInExpr(Res); 8855f757f3fSDimitry Andric } 8865f757f3fSDimitry Andric 887*7a6dacacSDimitry Andric ExprResult Parser::ParseOpenACCBindClauseArgument() { 888*7a6dacacSDimitry Andric // OpenACC 3.3 section 2.15: 889*7a6dacacSDimitry Andric // The bind clause specifies the name to use when calling the procedure on a 890*7a6dacacSDimitry Andric // device other than the host. If the name is specified as an identifier, it 891*7a6dacacSDimitry Andric // is called as if that name were specified in the language being compiled. If 892*7a6dacacSDimitry Andric // the name is specified as a string, the string is used for the procedure 893*7a6dacacSDimitry Andric // name unmodified. 894*7a6dacacSDimitry Andric if (getCurToken().is(tok::r_paren)) { 895*7a6dacacSDimitry Andric Diag(getCurToken(), diag::err_acc_incorrect_bind_arg); 896*7a6dacacSDimitry Andric return ExprError(); 897*7a6dacacSDimitry Andric } 898*7a6dacacSDimitry Andric 899*7a6dacacSDimitry Andric if (tok::isStringLiteral(getCurToken().getKind())) 900*7a6dacacSDimitry Andric return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression( 901*7a6dacacSDimitry Andric /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true)); 902*7a6dacacSDimitry Andric 903*7a6dacacSDimitry Andric return ParseOpenACCIDExpression(); 904*7a6dacacSDimitry Andric } 905*7a6dacacSDimitry Andric 906297eecfbSDimitry Andric /// OpenACC 3.3, section 1.6: 907297eecfbSDimitry Andric /// In this spec, a 'var' (in italics) is one of the following: 908297eecfbSDimitry Andric /// - a variable name (a scalar, array, or compisite variable name) 909297eecfbSDimitry Andric /// - a subarray specification with subscript ranges 910297eecfbSDimitry Andric /// - an array element 911297eecfbSDimitry Andric /// - a member of a composite variable 912297eecfbSDimitry Andric /// - a common block name between slashes (fortran only) 913297eecfbSDimitry Andric bool Parser::ParseOpenACCVar() { 914297eecfbSDimitry Andric OpenACCArraySectionRAII ArraySections(*this); 915*7a6dacacSDimitry Andric ExprResult Res = 916*7a6dacacSDimitry Andric getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 917297eecfbSDimitry Andric return Res.isInvalid(); 9185f757f3fSDimitry Andric } 9195f757f3fSDimitry Andric 9205f757f3fSDimitry Andric /// OpenACC 3.3, section 2.10: 9215f757f3fSDimitry Andric /// In C and C++, the syntax of the cache directive is: 9225f757f3fSDimitry Andric /// 9235f757f3fSDimitry Andric /// #pragma acc cache ([readonly:]var-list) new-line 9245f757f3fSDimitry Andric void Parser::ParseOpenACCCacheVarList() { 9255f757f3fSDimitry Andric // If this is the end of the line, just return 'false' and count on the close 9265f757f3fSDimitry Andric // paren diagnostic to catch the issue. 9275f757f3fSDimitry Andric if (getCurToken().isAnnotation()) 9285f757f3fSDimitry Andric return; 9295f757f3fSDimitry Andric 9305f757f3fSDimitry Andric // The VarList is an optional `readonly:` followed by a list of a variable 931*7a6dacacSDimitry Andric // specifications. Consume something that looks like a 'tag', and diagnose if 932*7a6dacacSDimitry Andric // it isn't 'readonly'. 933*7a6dacacSDimitry Andric if (tryParseAndConsumeSpecialTokenKind(*this, 934*7a6dacacSDimitry Andric OpenACCSpecialTokenKind::ReadOnly, 935*7a6dacacSDimitry Andric OpenACCDirectiveKind::Cache)) { 9365f757f3fSDimitry Andric // FIXME: Record that this is a 'readonly' so that we can use that during 9375f757f3fSDimitry Andric // Sema/AST generation. 9385f757f3fSDimitry Andric } 9395f757f3fSDimitry Andric 9405f757f3fSDimitry Andric bool FirstArray = true; 9415f757f3fSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 9425f757f3fSDimitry Andric if (!FirstArray) 9435f757f3fSDimitry Andric ExpectAndConsume(tok::comma); 9445f757f3fSDimitry Andric FirstArray = false; 945297eecfbSDimitry Andric 946297eecfbSDimitry Andric // OpenACC 3.3, section 2.10: 947297eecfbSDimitry Andric // A 'var' in a cache directive must be a single array element or a simple 948297eecfbSDimitry Andric // subarray. In C and C++, a simple subarray is an array name followed by 949297eecfbSDimitry Andric // an extended array range specification in brackets, with a start and 950297eecfbSDimitry Andric // length such as: 951297eecfbSDimitry Andric // 952297eecfbSDimitry Andric // arr[lower:length] 953297eecfbSDimitry Andric // 954297eecfbSDimitry Andric if (ParseOpenACCVar()) 9555f757f3fSDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma, 9565f757f3fSDimitry Andric StopBeforeMatch); 9575f757f3fSDimitry Andric } 9585f757f3fSDimitry Andric } 9595f757f3fSDimitry Andric 9605f757f3fSDimitry Andric void Parser::ParseOpenACCDirective() { 9615f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); 9625f757f3fSDimitry Andric 9635f757f3fSDimitry Andric // Once we've parsed the construct/directive name, some have additional 9645f757f3fSDimitry Andric // specifiers that need to be taken care of. Atomic has an 'atomic-clause' 9655f757f3fSDimitry Andric // that needs to be parsed. 9665f757f3fSDimitry Andric if (DirKind == OpenACCDirectiveKind::Atomic) 9675f757f3fSDimitry Andric ParseOpenACCAtomicKind(*this); 9685f757f3fSDimitry Andric 9695f757f3fSDimitry Andric // We've successfully parsed the construct/directive name, however a few of 9705f757f3fSDimitry Andric // the constructs have optional parens that contain further details. 9715f757f3fSDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, 9725f757f3fSDimitry Andric tok::annot_pragma_openacc_end); 9735f757f3fSDimitry Andric 9745f757f3fSDimitry Andric if (!T.consumeOpen()) { 9755f757f3fSDimitry Andric switch (DirKind) { 9765f757f3fSDimitry Andric default: 9775f757f3fSDimitry Andric Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren); 9785f757f3fSDimitry Andric T.skipToEnd(); 9795f757f3fSDimitry Andric break; 9805f757f3fSDimitry Andric case OpenACCDirectiveKind::Routine: { 9815f757f3fSDimitry Andric // Routine has an optional paren-wrapped name of a function in the local 9825f757f3fSDimitry Andric // scope. We parse the name, emitting any diagnostics 9835f757f3fSDimitry Andric ExprResult RoutineName = ParseOpenACCIDExpression(); 9845f757f3fSDimitry Andric // If the routine name is invalid, just skip until the closing paren to 9855f757f3fSDimitry Andric // recover more gracefully. 9865f757f3fSDimitry Andric if (RoutineName.isInvalid()) 9875f757f3fSDimitry Andric T.skipToEnd(); 9885f757f3fSDimitry Andric else 9895f757f3fSDimitry Andric T.consumeClose(); 9905f757f3fSDimitry Andric break; 9915f757f3fSDimitry Andric } 9925f757f3fSDimitry Andric case OpenACCDirectiveKind::Cache: 9935f757f3fSDimitry Andric ParseOpenACCCacheVarList(); 9945f757f3fSDimitry Andric // The ParseOpenACCCacheVarList function manages to recover from failures, 9955f757f3fSDimitry Andric // so we can always consume the close. 9965f757f3fSDimitry Andric T.consumeClose(); 9975f757f3fSDimitry Andric break; 9985f757f3fSDimitry Andric case OpenACCDirectiveKind::Wait: 9995f757f3fSDimitry Andric // OpenACC has an optional paren-wrapped 'wait-argument'. 10005f757f3fSDimitry Andric if (ParseOpenACCWaitArgument()) 10015f757f3fSDimitry Andric T.skipToEnd(); 10025f757f3fSDimitry Andric else 10035f757f3fSDimitry Andric T.consumeClose(); 10045f757f3fSDimitry Andric break; 10055f757f3fSDimitry Andric } 10065f757f3fSDimitry Andric } else if (DirKind == OpenACCDirectiveKind::Cache) { 10075f757f3fSDimitry Andric // Cache's paren var-list is required, so error here if it isn't provided. 10085f757f3fSDimitry Andric // We know that the consumeOpen above left the first non-paren here, so 10095f757f3fSDimitry Andric // diagnose, then continue as if it was completely omitted. 10105f757f3fSDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren; 10115f757f3fSDimitry Andric } 10125f757f3fSDimitry Andric 10135f757f3fSDimitry Andric // Parses the list of clauses, if present. 1014*7a6dacacSDimitry Andric ParseOpenACCClauseList(DirKind); 10155f757f3fSDimitry Andric 10165f757f3fSDimitry Andric Diag(getCurToken(), diag::warn_pragma_acc_unimplemented); 1017cb14a3feSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc_end) && 1018cb14a3feSDimitry Andric "Didn't parse all OpenACC Clauses"); 1019cb14a3feSDimitry Andric ConsumeAnnotationToken(); 10205f757f3fSDimitry Andric } 10215f757f3fSDimitry Andric 10225f757f3fSDimitry Andric // Parse OpenACC directive on a declaration. 10235f757f3fSDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { 10245f757f3fSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 10255f757f3fSDimitry Andric 10265f757f3fSDimitry Andric ParsingOpenACCDirectiveRAII DirScope(*this); 10275f757f3fSDimitry Andric ConsumeAnnotationToken(); 10285f757f3fSDimitry Andric 10295f757f3fSDimitry Andric ParseOpenACCDirective(); 10305f757f3fSDimitry Andric 10315f757f3fSDimitry Andric return nullptr; 10325f757f3fSDimitry Andric } 10335f757f3fSDimitry Andric 10345f757f3fSDimitry Andric // Parse OpenACC Directive on a Statement. 10355f757f3fSDimitry Andric StmtResult Parser::ParseOpenACCDirectiveStmt() { 10365f757f3fSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 10375f757f3fSDimitry Andric 10385f757f3fSDimitry Andric ParsingOpenACCDirectiveRAII DirScope(*this); 10395f757f3fSDimitry Andric ConsumeAnnotationToken(); 10405f757f3fSDimitry Andric 10415f757f3fSDimitry Andric ParseOpenACCDirective(); 10425f757f3fSDimitry Andric 10435f757f3fSDimitry Andric return StmtEmpty(); 10445f757f3fSDimitry Andric } 1045