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()) 92cb14a3feSDimitry Andric .Case("auto", OpenACCClauseKind::Auto) 931db9f3b2SDimitry Andric .Case("default", OpenACCClauseKind::Default) 94cb14a3feSDimitry Andric .Case("finalize", OpenACCClauseKind::Finalize) 951db9f3b2SDimitry Andric .Case("if", OpenACCClauseKind::If) 96cb14a3feSDimitry Andric .Case("if_present", OpenACCClauseKind::IfPresent) 97cb14a3feSDimitry Andric .Case("independent", OpenACCClauseKind::Independent) 98cb14a3feSDimitry Andric .Case("nohost", OpenACCClauseKind::NoHost) 991db9f3b2SDimitry Andric .Case("self", OpenACCClauseKind::Self) 100cb14a3feSDimitry Andric .Case("seq", OpenACCClauseKind::Seq) 101cb14a3feSDimitry Andric .Case("vector", OpenACCClauseKind::Vector) 102cb14a3feSDimitry Andric .Case("worker", OpenACCClauseKind::Worker) 103cb14a3feSDimitry Andric .Default(OpenACCClauseKind::Invalid); 104cb14a3feSDimitry Andric } 105cb14a3feSDimitry Andric 1065f757f3fSDimitry Andric // Since 'atomic' is effectively a compound directive, this will decode the 1075f757f3fSDimitry Andric // second part of the directive. 1085f757f3fSDimitry Andric OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { 1095f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 1105f757f3fSDimitry Andric return OpenACCAtomicKind::Invalid; 1115f757f3fSDimitry Andric return llvm::StringSwitch<OpenACCAtomicKind>( 1125f757f3fSDimitry Andric Tok.getIdentifierInfo()->getName()) 1135f757f3fSDimitry Andric .Case("read", OpenACCAtomicKind::Read) 1145f757f3fSDimitry Andric .Case("write", OpenACCAtomicKind::Write) 1155f757f3fSDimitry Andric .Case("update", OpenACCAtomicKind::Update) 1165f757f3fSDimitry Andric .Case("capture", OpenACCAtomicKind::Capture) 1175f757f3fSDimitry Andric .Default(OpenACCAtomicKind::Invalid); 1185f757f3fSDimitry Andric } 1195f757f3fSDimitry Andric 1201db9f3b2SDimitry Andric OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) { 1211db9f3b2SDimitry Andric if (!Tok.is(tok::identifier)) 1221db9f3b2SDimitry Andric return OpenACCDefaultClauseKind::Invalid; 1231db9f3b2SDimitry Andric 1241db9f3b2SDimitry Andric return llvm::StringSwitch<OpenACCDefaultClauseKind>( 1251db9f3b2SDimitry Andric Tok.getIdentifierInfo()->getName()) 1261db9f3b2SDimitry Andric .Case("none", OpenACCDefaultClauseKind::None) 1271db9f3b2SDimitry Andric .Case("present", OpenACCDefaultClauseKind::Present) 1281db9f3b2SDimitry Andric .Default(OpenACCDefaultClauseKind::Invalid); 1291db9f3b2SDimitry Andric } 1301db9f3b2SDimitry Andric 1315f757f3fSDimitry Andric enum class OpenACCSpecialTokenKind { 1325f757f3fSDimitry Andric ReadOnly, 1335f757f3fSDimitry Andric DevNum, 1345f757f3fSDimitry Andric Queues, 1355f757f3fSDimitry Andric }; 1365f757f3fSDimitry Andric 1375f757f3fSDimitry Andric bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { 1385f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 1395f757f3fSDimitry Andric return false; 1405f757f3fSDimitry Andric 1415f757f3fSDimitry Andric switch (Kind) { 1425f757f3fSDimitry Andric case OpenACCSpecialTokenKind::ReadOnly: 1435f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("readonly"); 1445f757f3fSDimitry Andric case OpenACCSpecialTokenKind::DevNum: 1455f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("devnum"); 1465f757f3fSDimitry Andric case OpenACCSpecialTokenKind::Queues: 1475f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("queues"); 1485f757f3fSDimitry Andric } 1495f757f3fSDimitry Andric llvm_unreachable("Unknown 'Kind' Passed"); 1505f757f3fSDimitry Andric } 1515f757f3fSDimitry Andric 1525f757f3fSDimitry Andric bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { 1535f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 1545f757f3fSDimitry Andric return false; 1555f757f3fSDimitry Andric 1565f757f3fSDimitry Andric switch (Kind) { 1575f757f3fSDimitry Andric case OpenACCDirectiveKind::Parallel: 1585f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("parallel"); 1595f757f3fSDimitry Andric case OpenACCDirectiveKind::Serial: 1605f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("serial"); 1615f757f3fSDimitry Andric case OpenACCDirectiveKind::Kernels: 1625f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("kernels"); 1635f757f3fSDimitry Andric case OpenACCDirectiveKind::Data: 1645f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("data"); 1655f757f3fSDimitry Andric case OpenACCDirectiveKind::HostData: 1665f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("host_data"); 1675f757f3fSDimitry Andric case OpenACCDirectiveKind::Loop: 1685f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("loop"); 1695f757f3fSDimitry Andric case OpenACCDirectiveKind::Cache: 1705f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("cache"); 1715f757f3fSDimitry Andric 1725f757f3fSDimitry Andric case OpenACCDirectiveKind::ParallelLoop: 1735f757f3fSDimitry Andric case OpenACCDirectiveKind::SerialLoop: 1745f757f3fSDimitry Andric case OpenACCDirectiveKind::KernelsLoop: 1755f757f3fSDimitry Andric case OpenACCDirectiveKind::EnterData: 1765f757f3fSDimitry Andric case OpenACCDirectiveKind::ExitData: 1775f757f3fSDimitry Andric return false; 1785f757f3fSDimitry Andric 1795f757f3fSDimitry Andric case OpenACCDirectiveKind::Atomic: 1805f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("atomic"); 1815f757f3fSDimitry Andric case OpenACCDirectiveKind::Routine: 1825f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("routine"); 1835f757f3fSDimitry Andric case OpenACCDirectiveKind::Declare: 1845f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("declare"); 1855f757f3fSDimitry Andric case OpenACCDirectiveKind::Init: 1865f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("init"); 1875f757f3fSDimitry Andric case OpenACCDirectiveKind::Shutdown: 1885f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("shutdown"); 1895f757f3fSDimitry Andric case OpenACCDirectiveKind::Set: 1905f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("set"); 1915f757f3fSDimitry Andric case OpenACCDirectiveKind::Update: 1925f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("update"); 1935f757f3fSDimitry Andric case OpenACCDirectiveKind::Wait: 1945f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("wait"); 1955f757f3fSDimitry Andric case OpenACCDirectiveKind::Invalid: 1965f757f3fSDimitry Andric return false; 1975f757f3fSDimitry Andric } 1985f757f3fSDimitry Andric llvm_unreachable("Unknown 'Kind' Passed"); 1995f757f3fSDimitry Andric } 2005f757f3fSDimitry Andric 2011db9f3b2SDimitry Andric /// Used for cases where we expect an identifier-like token, but don't want to 2021db9f3b2SDimitry Andric /// give awkward error messages in cases where it is accidentially a keyword. 2031db9f3b2SDimitry Andric bool expectIdentifierOrKeyword(Parser &P) { 2041db9f3b2SDimitry Andric Token Tok = P.getCurToken(); 2051db9f3b2SDimitry Andric 2061db9f3b2SDimitry Andric if (Tok.is(tok::identifier)) 2071db9f3b2SDimitry Andric return false; 2081db9f3b2SDimitry Andric 2091db9f3b2SDimitry Andric if (!Tok.isAnnotation() && Tok.getIdentifierInfo() && 2101db9f3b2SDimitry Andric Tok.getIdentifierInfo()->isKeyword(P.getLangOpts())) 2111db9f3b2SDimitry Andric return false; 2121db9f3b2SDimitry Andric 2131db9f3b2SDimitry Andric P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; 2141db9f3b2SDimitry Andric return true; 2151db9f3b2SDimitry Andric } 2161db9f3b2SDimitry Andric 2175f757f3fSDimitry Andric OpenACCDirectiveKind 2185f757f3fSDimitry Andric ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, 2195f757f3fSDimitry Andric OpenACCDirectiveKindEx ExtDirKind) { 2205f757f3fSDimitry Andric Token SecondTok = P.getCurToken(); 2215f757f3fSDimitry Andric 2225f757f3fSDimitry Andric if (SecondTok.isAnnotation()) { 2235f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 2245f757f3fSDimitry Andric << 0 << FirstTok.getIdentifierInfo(); 2255f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 2265f757f3fSDimitry Andric } 2275f757f3fSDimitry Andric 228cb14a3feSDimitry Andric // Consume the second name anyway, this way we can continue on without making 229cb14a3feSDimitry Andric // this oddly look like a clause. 230cb14a3feSDimitry Andric P.ConsumeAnyToken(); 231cb14a3feSDimitry Andric 2325f757f3fSDimitry Andric if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { 2335f757f3fSDimitry Andric if (!SecondTok.is(tok::identifier)) 2345f757f3fSDimitry Andric P.Diag(SecondTok, diag::err_expected) << tok::identifier; 2355f757f3fSDimitry Andric else 2365f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 2375f757f3fSDimitry Andric << 1 << FirstTok.getIdentifierInfo()->getName() 2385f757f3fSDimitry Andric << SecondTok.getIdentifierInfo()->getName(); 2395f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 2405f757f3fSDimitry Andric } 2415f757f3fSDimitry Andric 2425f757f3fSDimitry Andric return ExtDirKind == OpenACCDirectiveKindEx::Enter 2435f757f3fSDimitry Andric ? OpenACCDirectiveKind::EnterData 2445f757f3fSDimitry Andric : OpenACCDirectiveKind::ExitData; 2455f757f3fSDimitry Andric } 2465f757f3fSDimitry Andric 2475f757f3fSDimitry Andric OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) { 2485f757f3fSDimitry Andric Token AtomicClauseToken = P.getCurToken(); 2495f757f3fSDimitry Andric 2505f757f3fSDimitry Andric // #pragma acc atomic is equivilent to update: 2515f757f3fSDimitry Andric if (AtomicClauseToken.isAnnotation()) 2525f757f3fSDimitry Andric return OpenACCAtomicKind::Update; 2535f757f3fSDimitry Andric 2545f757f3fSDimitry Andric OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken); 2555f757f3fSDimitry Andric 2565f757f3fSDimitry Andric // If we don't know what this is, treat it as 'nothing', and treat the rest of 2575f757f3fSDimitry Andric // this as a clause list, which, despite being invalid, is likely what the 2585f757f3fSDimitry Andric // user was trying to do. 2595f757f3fSDimitry Andric if (AtomicKind == OpenACCAtomicKind::Invalid) 2605f757f3fSDimitry Andric return OpenACCAtomicKind::Update; 2615f757f3fSDimitry Andric 2625f757f3fSDimitry Andric P.ConsumeToken(); 2635f757f3fSDimitry Andric return AtomicKind; 2645f757f3fSDimitry Andric } 2655f757f3fSDimitry Andric 2665f757f3fSDimitry Andric // Parse and consume the tokens for OpenACC Directive/Construct kinds. 2675f757f3fSDimitry Andric OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { 2685f757f3fSDimitry Andric Token FirstTok = P.getCurToken(); 2695f757f3fSDimitry Andric 2705f757f3fSDimitry Andric // Just #pragma acc can get us immediately to the end, make sure we don't 2715f757f3fSDimitry Andric // introspect on the spelling before then. 2725f757f3fSDimitry Andric if (FirstTok.isNot(tok::identifier)) { 2735f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_missing_directive); 274cb14a3feSDimitry Andric 275cb14a3feSDimitry Andric if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 276cb14a3feSDimitry Andric P.ConsumeAnyToken(); 277cb14a3feSDimitry Andric 2785f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 2795f757f3fSDimitry Andric } 2805f757f3fSDimitry Andric 2815f757f3fSDimitry Andric P.ConsumeToken(); 2825f757f3fSDimitry Andric 2835f757f3fSDimitry Andric OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok); 2845f757f3fSDimitry Andric 2855f757f3fSDimitry Andric // OpenACCDirectiveKindEx is meant to be an extended list 2865f757f3fSDimitry Andric // over OpenACCDirectiveKind, so any value below Invalid is one of the 2875f757f3fSDimitry Andric // OpenACCDirectiveKind values. This switch takes care of all of the extra 2885f757f3fSDimitry Andric // parsing required for the Extended values. At the end of this block, 2895f757f3fSDimitry Andric // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can 2905f757f3fSDimitry Andric // immediately cast it and use it as that. 2915f757f3fSDimitry Andric if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) { 2925f757f3fSDimitry Andric switch (ExDirKind) { 2935f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Invalid: { 2945f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 2955f757f3fSDimitry Andric << 0 << FirstTok.getIdentifierInfo(); 2965f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 2975f757f3fSDimitry Andric } 2985f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Enter: 2995f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Exit: 3005f757f3fSDimitry Andric return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind); 3015f757f3fSDimitry Andric } 3025f757f3fSDimitry Andric } 3035f757f3fSDimitry Andric 3045f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind); 3055f757f3fSDimitry Andric 3065f757f3fSDimitry Andric // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any 3075f757f3fSDimitry Andric // other attempt at a combined construct will be diagnosed as an invalid 3085f757f3fSDimitry Andric // clause. 3095f757f3fSDimitry Andric Token SecondTok = P.getCurToken(); 3105f757f3fSDimitry Andric if (!SecondTok.isAnnotation() && 3115f757f3fSDimitry Andric isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) { 3125f757f3fSDimitry Andric switch (DirKind) { 3135f757f3fSDimitry Andric default: 3145f757f3fSDimitry Andric // Nothing to do except in the below cases, as they should be diagnosed as 3155f757f3fSDimitry Andric // a clause. 3165f757f3fSDimitry Andric break; 3175f757f3fSDimitry Andric case OpenACCDirectiveKind::Parallel: 3185f757f3fSDimitry Andric P.ConsumeToken(); 3195f757f3fSDimitry Andric return OpenACCDirectiveKind::ParallelLoop; 3205f757f3fSDimitry Andric case OpenACCDirectiveKind::Serial: 3215f757f3fSDimitry Andric P.ConsumeToken(); 3225f757f3fSDimitry Andric return OpenACCDirectiveKind::SerialLoop; 3235f757f3fSDimitry Andric case OpenACCDirectiveKind::Kernels: 3245f757f3fSDimitry Andric P.ConsumeToken(); 3255f757f3fSDimitry Andric return OpenACCDirectiveKind::KernelsLoop; 3265f757f3fSDimitry Andric } 3275f757f3fSDimitry Andric } 3285f757f3fSDimitry Andric 3295f757f3fSDimitry Andric return DirKind; 3305f757f3fSDimitry Andric } 3315f757f3fSDimitry Andric 3321db9f3b2SDimitry Andric bool ClauseHasOptionalParens(OpenACCClauseKind Kind) { 3331db9f3b2SDimitry Andric return Kind == OpenACCClauseKind::Self; 3341db9f3b2SDimitry Andric } 3351db9f3b2SDimitry Andric 3361db9f3b2SDimitry Andric bool ClauseHasRequiredParens(OpenACCClauseKind Kind) { 3371db9f3b2SDimitry Andric return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If; 3381db9f3b2SDimitry Andric } 3391db9f3b2SDimitry Andric 3401db9f3b2SDimitry Andric ExprResult ParseOpenACCConditionalExpr(Parser &P) { 3411db9f3b2SDimitry Andric // FIXME: It isn't clear if the spec saying 'condition' means the same as 3421db9f3b2SDimitry Andric // it does in an if/while/etc (See ParseCXXCondition), however as it was 3431db9f3b2SDimitry Andric // written with Fortran/C in mind, we're going to assume it just means an 3441db9f3b2SDimitry Andric // 'expression evaluating to boolean'. 3451db9f3b2SDimitry Andric return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression()); 3461db9f3b2SDimitry Andric } 3471db9f3b2SDimitry Andric 3481db9f3b2SDimitry Andric bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) { 3491db9f3b2SDimitry Andric BalancedDelimiterTracker Parens(P, tok::l_paren, 3501db9f3b2SDimitry Andric tok::annot_pragma_openacc_end); 3511db9f3b2SDimitry Andric 3521db9f3b2SDimitry Andric if (ClauseHasRequiredParens(Kind)) { 3531db9f3b2SDimitry Andric if (Parens.expectAndConsume()) { 3541db9f3b2SDimitry Andric // We are missing a paren, so assume that the person just forgot the 3551db9f3b2SDimitry Andric // parameter. Return 'false' so we try to continue on and parse the next 3561db9f3b2SDimitry Andric // clause. 3571db9f3b2SDimitry Andric P.SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, 3581db9f3b2SDimitry Andric Parser::StopBeforeMatch); 3591db9f3b2SDimitry Andric return false; 3601db9f3b2SDimitry Andric } 3611db9f3b2SDimitry Andric 3621db9f3b2SDimitry Andric switch (Kind) { 3631db9f3b2SDimitry Andric case OpenACCClauseKind::Default: { 3641db9f3b2SDimitry Andric Token DefKindTok = P.getCurToken(); 3651db9f3b2SDimitry Andric 3661db9f3b2SDimitry Andric if (expectIdentifierOrKeyword(P)) 3671db9f3b2SDimitry Andric break; 3681db9f3b2SDimitry Andric 3691db9f3b2SDimitry Andric P.ConsumeToken(); 3701db9f3b2SDimitry Andric 3711db9f3b2SDimitry Andric if (getOpenACCDefaultClauseKind(DefKindTok) == 3721db9f3b2SDimitry Andric OpenACCDefaultClauseKind::Invalid) 3731db9f3b2SDimitry Andric P.Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); 3741db9f3b2SDimitry Andric 3751db9f3b2SDimitry Andric break; 3761db9f3b2SDimitry Andric } 3771db9f3b2SDimitry Andric case OpenACCClauseKind::If: { 3781db9f3b2SDimitry Andric ExprResult CondExpr = ParseOpenACCConditionalExpr(P); 3791db9f3b2SDimitry Andric // An invalid expression can be just about anything, so just give up on 3801db9f3b2SDimitry Andric // this clause list. 3811db9f3b2SDimitry Andric if (CondExpr.isInvalid()) 3821db9f3b2SDimitry Andric return true; 3831db9f3b2SDimitry Andric break; 3841db9f3b2SDimitry Andric } 3851db9f3b2SDimitry Andric default: 3861db9f3b2SDimitry Andric llvm_unreachable("Not a required parens type?"); 3871db9f3b2SDimitry Andric } 3881db9f3b2SDimitry Andric 3891db9f3b2SDimitry Andric return Parens.consumeClose(); 3901db9f3b2SDimitry Andric } else if (ClauseHasOptionalParens(Kind)) { 3911db9f3b2SDimitry Andric if (!Parens.consumeOpen()) { 3921db9f3b2SDimitry Andric switch (Kind) { 3931db9f3b2SDimitry Andric case OpenACCClauseKind::Self: { 3941db9f3b2SDimitry Andric ExprResult CondExpr = ParseOpenACCConditionalExpr(P); 3951db9f3b2SDimitry Andric // An invalid expression can be just about anything, so just give up on 3961db9f3b2SDimitry Andric // this clause list. 3971db9f3b2SDimitry Andric if (CondExpr.isInvalid()) 3981db9f3b2SDimitry Andric return true; 3991db9f3b2SDimitry Andric break; 4001db9f3b2SDimitry Andric } 4011db9f3b2SDimitry Andric default: 4021db9f3b2SDimitry Andric llvm_unreachable("Not an optional parens type?"); 4031db9f3b2SDimitry Andric } 4041db9f3b2SDimitry Andric Parens.consumeClose(); 4051db9f3b2SDimitry Andric } 4061db9f3b2SDimitry Andric } 4071db9f3b2SDimitry Andric return false; 4081db9f3b2SDimitry Andric } 4091db9f3b2SDimitry Andric 410cb14a3feSDimitry Andric // The OpenACC Clause List is a comma or space-delimited list of clauses (see 411cb14a3feSDimitry Andric // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't 412cb14a3feSDimitry Andric // really have its owner grammar and each individual one has its own definition. 4131db9f3b2SDimitry Andric // However, they all are named with a single-identifier (or auto/default!) 4141db9f3b2SDimitry Andric // token, followed in some cases by either braces or parens. 415cb14a3feSDimitry Andric bool ParseOpenACCClause(Parser &P) { 4161db9f3b2SDimitry Andric // A number of clause names are actually keywords, so accept a keyword that 4171db9f3b2SDimitry Andric // can be converted to a name. 4181db9f3b2SDimitry Andric if (expectIdentifierOrKeyword(P)) 4191db9f3b2SDimitry Andric return true; 420cb14a3feSDimitry Andric 421cb14a3feSDimitry Andric OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken()); 422cb14a3feSDimitry Andric 423cb14a3feSDimitry Andric if (Kind == OpenACCClauseKind::Invalid) 424cb14a3feSDimitry Andric return P.Diag(P.getCurToken(), diag::err_acc_invalid_clause) 425cb14a3feSDimitry Andric << P.getCurToken().getIdentifierInfo(); 426cb14a3feSDimitry Andric 427cb14a3feSDimitry Andric // Consume the clause name. 428cb14a3feSDimitry Andric P.ConsumeToken(); 429cb14a3feSDimitry Andric 4301db9f3b2SDimitry Andric return ParseOpenACCClauseParams(P, Kind); 431cb14a3feSDimitry Andric } 432cb14a3feSDimitry Andric 433cb14a3feSDimitry Andric // Skip until we see the end of pragma token, but don't consume it. This is us 434cb14a3feSDimitry Andric // just giving up on the rest of the pragma so we can continue executing. We 435cb14a3feSDimitry Andric // have to do this because 'SkipUntil' considers paren balancing, which isn't 436cb14a3feSDimitry Andric // what we want. 437cb14a3feSDimitry Andric void SkipUntilEndOfDirective(Parser &P) { 438cb14a3feSDimitry Andric while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 439cb14a3feSDimitry Andric P.ConsumeAnyToken(); 440cb14a3feSDimitry Andric } 441cb14a3feSDimitry Andric 442cb14a3feSDimitry Andric // OpenACC 3.3, section 1.7: 443cb14a3feSDimitry Andric // To simplify the specification and convey appropriate constraint information, 444cb14a3feSDimitry Andric // a pqr-list is a comma-separated list of pdr items. The one exception is a 445cb14a3feSDimitry Andric // clause-list, which is a list of one or more clauses optionally separated by 446cb14a3feSDimitry Andric // commas. 4475f757f3fSDimitry Andric void ParseOpenACCClauseList(Parser &P) { 448cb14a3feSDimitry Andric bool FirstClause = true; 449cb14a3feSDimitry Andric while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) { 450cb14a3feSDimitry Andric // Comma is optional in a clause-list. 451cb14a3feSDimitry Andric if (!FirstClause && P.getCurToken().is(tok::comma)) 452cb14a3feSDimitry Andric P.ConsumeToken(); 453cb14a3feSDimitry Andric FirstClause = false; 454cb14a3feSDimitry Andric 455cb14a3feSDimitry Andric // Recovering from a bad clause is really difficult, so we just give up on 456cb14a3feSDimitry Andric // error. 457cb14a3feSDimitry Andric if (ParseOpenACCClause(P)) { 458cb14a3feSDimitry Andric SkipUntilEndOfDirective(P); 459cb14a3feSDimitry Andric return; 460cb14a3feSDimitry Andric } 461cb14a3feSDimitry Andric } 4625f757f3fSDimitry Andric } 4635f757f3fSDimitry Andric 4645f757f3fSDimitry Andric } // namespace 4655f757f3fSDimitry Andric 4665f757f3fSDimitry Andric /// OpenACC 3.3, section 2.16: 4675f757f3fSDimitry Andric /// In this section and throughout the specification, the term wait-argument 4685f757f3fSDimitry Andric /// means: 4695f757f3fSDimitry Andric /// [ devnum : int-expr : ] [ queues : ] async-argument-list 4705f757f3fSDimitry Andric bool Parser::ParseOpenACCWaitArgument() { 4715f757f3fSDimitry Andric // [devnum : int-expr : ] 4725f757f3fSDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && 4735f757f3fSDimitry Andric NextToken().is(tok::colon)) { 4745f757f3fSDimitry Andric // Consume devnum. 4755f757f3fSDimitry Andric ConsumeToken(); 4765f757f3fSDimitry Andric // Consume colon. 4775f757f3fSDimitry Andric ConsumeToken(); 4785f757f3fSDimitry Andric 4795f757f3fSDimitry Andric ExprResult IntExpr = 4805f757f3fSDimitry Andric getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 4815f757f3fSDimitry Andric if (IntExpr.isInvalid()) 4825f757f3fSDimitry Andric return true; 4835f757f3fSDimitry Andric 4845f757f3fSDimitry Andric if (ExpectAndConsume(tok::colon)) 4855f757f3fSDimitry Andric return true; 4865f757f3fSDimitry Andric } 4875f757f3fSDimitry Andric 4885f757f3fSDimitry Andric // [ queues : ] 4895f757f3fSDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && 4905f757f3fSDimitry Andric NextToken().is(tok::colon)) { 4915f757f3fSDimitry Andric // Consume queues. 4925f757f3fSDimitry Andric ConsumeToken(); 4935f757f3fSDimitry Andric // Consume colon. 4945f757f3fSDimitry Andric ConsumeToken(); 4955f757f3fSDimitry Andric } 4965f757f3fSDimitry Andric 4975f757f3fSDimitry Andric // OpenACC 3.3, section 2.16: 4985f757f3fSDimitry Andric // the term 'async-argument' means a nonnegative scalar integer expression, or 4995f757f3fSDimitry Andric // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined 5005f757f3fSDimitry Andric // in the C header file and the Fortran opacc module. 5015f757f3fSDimitry Andric // 5025f757f3fSDimitry Andric // We are parsing this simply as list of assignment expressions (to avoid 5035f757f3fSDimitry Andric // comma being troublesome), and will ensure it is an integral type. The 5045f757f3fSDimitry Andric // 'special' types are defined as macros, so we can't really check those 5055f757f3fSDimitry Andric // (other than perhaps as values at one point?), but the standard does say it 5065f757f3fSDimitry Andric // is implementation-defined to use any other negative value. 5075f757f3fSDimitry Andric // 5085f757f3fSDimitry Andric // 5095f757f3fSDimitry Andric bool FirstArg = true; 5105f757f3fSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 5115f757f3fSDimitry Andric if (!FirstArg) { 5125f757f3fSDimitry Andric if (ExpectAndConsume(tok::comma)) 5135f757f3fSDimitry Andric return true; 5145f757f3fSDimitry Andric } 5155f757f3fSDimitry Andric FirstArg = false; 5165f757f3fSDimitry Andric 5175f757f3fSDimitry Andric ExprResult CurArg = 5185f757f3fSDimitry Andric getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 5195f757f3fSDimitry Andric 5205f757f3fSDimitry Andric if (CurArg.isInvalid()) 5215f757f3fSDimitry Andric return true; 5225f757f3fSDimitry Andric } 5235f757f3fSDimitry Andric 5245f757f3fSDimitry Andric return false; 5255f757f3fSDimitry Andric } 5265f757f3fSDimitry Andric 5275f757f3fSDimitry Andric ExprResult Parser::ParseOpenACCIDExpression() { 5285f757f3fSDimitry Andric ExprResult Res; 5295f757f3fSDimitry Andric if (getLangOpts().CPlusPlus) { 5305f757f3fSDimitry Andric Res = ParseCXXIdExpression(/*isAddressOfOperand=*/false); 5315f757f3fSDimitry Andric } else { 5325f757f3fSDimitry Andric // There isn't anything quite the same as ParseCXXIdExpression for C, so we 5335f757f3fSDimitry Andric // need to get the identifier, then call into Sema ourselves. 5345f757f3fSDimitry Andric 5355f757f3fSDimitry Andric if (Tok.isNot(tok::identifier)) { 5365f757f3fSDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier; 5375f757f3fSDimitry Andric return ExprError(); 5385f757f3fSDimitry Andric } 5395f757f3fSDimitry Andric 5405f757f3fSDimitry Andric Token FuncName = getCurToken(); 5415f757f3fSDimitry Andric UnqualifiedId Name; 5425f757f3fSDimitry Andric CXXScopeSpec ScopeSpec; 5435f757f3fSDimitry Andric SourceLocation TemplateKWLoc; 5445f757f3fSDimitry Andric Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken()); 5455f757f3fSDimitry Andric 5465f757f3fSDimitry Andric // Ensure this is a valid identifier. We don't accept causing implicit 5475f757f3fSDimitry Andric // function declarations per the spec, so always claim to not have trailing 5485f757f3fSDimitry Andric // L Paren. 5495f757f3fSDimitry Andric Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, 5505f757f3fSDimitry Andric Name, /*HasTrailingLParen=*/false, 5515f757f3fSDimitry Andric /*isAddressOfOperand=*/false); 5525f757f3fSDimitry Andric } 5535f757f3fSDimitry Andric 5545f757f3fSDimitry Andric return getActions().CorrectDelayedTyposInExpr(Res); 5555f757f3fSDimitry Andric } 5565f757f3fSDimitry Andric 557*297eecfbSDimitry Andric /// OpenACC 3.3, section 1.6: 558*297eecfbSDimitry Andric /// In this spec, a 'var' (in italics) is one of the following: 559*297eecfbSDimitry Andric /// - a variable name (a scalar, array, or compisite variable name) 560*297eecfbSDimitry Andric /// - a subarray specification with subscript ranges 561*297eecfbSDimitry Andric /// - an array element 562*297eecfbSDimitry Andric /// - a member of a composite variable 563*297eecfbSDimitry Andric /// - a common block name between slashes (fortran only) 564*297eecfbSDimitry Andric bool Parser::ParseOpenACCVar() { 565*297eecfbSDimitry Andric OpenACCArraySectionRAII ArraySections(*this); 566*297eecfbSDimitry Andric ExprResult Res = ParseAssignmentExpression(); 567*297eecfbSDimitry Andric return Res.isInvalid(); 5685f757f3fSDimitry Andric } 5695f757f3fSDimitry Andric 5705f757f3fSDimitry Andric /// OpenACC 3.3, section 2.10: 5715f757f3fSDimitry Andric /// In C and C++, the syntax of the cache directive is: 5725f757f3fSDimitry Andric /// 5735f757f3fSDimitry Andric /// #pragma acc cache ([readonly:]var-list) new-line 5745f757f3fSDimitry Andric void Parser::ParseOpenACCCacheVarList() { 5755f757f3fSDimitry Andric // If this is the end of the line, just return 'false' and count on the close 5765f757f3fSDimitry Andric // paren diagnostic to catch the issue. 5775f757f3fSDimitry Andric if (getCurToken().isAnnotation()) 5785f757f3fSDimitry Andric return; 5795f757f3fSDimitry Andric 5805f757f3fSDimitry Andric // The VarList is an optional `readonly:` followed by a list of a variable 5815f757f3fSDimitry Andric // specifications. First, see if we have `readonly:`, else we back-out and 5825f757f3fSDimitry Andric // treat it like the beginning of a reference to a potentially-existing 5835f757f3fSDimitry Andric // `readonly` variable. 5845f757f3fSDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::ReadOnly, Tok) && 5855f757f3fSDimitry Andric NextToken().is(tok::colon)) { 5865f757f3fSDimitry Andric // Consume both tokens. 5875f757f3fSDimitry Andric ConsumeToken(); 5885f757f3fSDimitry Andric ConsumeToken(); 5895f757f3fSDimitry Andric // FIXME: Record that this is a 'readonly' so that we can use that during 5905f757f3fSDimitry Andric // Sema/AST generation. 5915f757f3fSDimitry Andric } 5925f757f3fSDimitry Andric 5935f757f3fSDimitry Andric bool FirstArray = true; 5945f757f3fSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 5955f757f3fSDimitry Andric if (!FirstArray) 5965f757f3fSDimitry Andric ExpectAndConsume(tok::comma); 5975f757f3fSDimitry Andric FirstArray = false; 598*297eecfbSDimitry Andric 599*297eecfbSDimitry Andric // OpenACC 3.3, section 2.10: 600*297eecfbSDimitry Andric // A 'var' in a cache directive must be a single array element or a simple 601*297eecfbSDimitry Andric // subarray. In C and C++, a simple subarray is an array name followed by 602*297eecfbSDimitry Andric // an extended array range specification in brackets, with a start and 603*297eecfbSDimitry Andric // length such as: 604*297eecfbSDimitry Andric // 605*297eecfbSDimitry Andric // arr[lower:length] 606*297eecfbSDimitry Andric // 607*297eecfbSDimitry Andric if (ParseOpenACCVar()) 6085f757f3fSDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma, 6095f757f3fSDimitry Andric StopBeforeMatch); 6105f757f3fSDimitry Andric } 6115f757f3fSDimitry Andric } 6125f757f3fSDimitry Andric 6135f757f3fSDimitry Andric void Parser::ParseOpenACCDirective() { 6145f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); 6155f757f3fSDimitry Andric 6165f757f3fSDimitry Andric // Once we've parsed the construct/directive name, some have additional 6175f757f3fSDimitry Andric // specifiers that need to be taken care of. Atomic has an 'atomic-clause' 6185f757f3fSDimitry Andric // that needs to be parsed. 6195f757f3fSDimitry Andric if (DirKind == OpenACCDirectiveKind::Atomic) 6205f757f3fSDimitry Andric ParseOpenACCAtomicKind(*this); 6215f757f3fSDimitry Andric 6225f757f3fSDimitry Andric // We've successfully parsed the construct/directive name, however a few of 6235f757f3fSDimitry Andric // the constructs have optional parens that contain further details. 6245f757f3fSDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, 6255f757f3fSDimitry Andric tok::annot_pragma_openacc_end); 6265f757f3fSDimitry Andric 6275f757f3fSDimitry Andric if (!T.consumeOpen()) { 6285f757f3fSDimitry Andric switch (DirKind) { 6295f757f3fSDimitry Andric default: 6305f757f3fSDimitry Andric Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren); 6315f757f3fSDimitry Andric T.skipToEnd(); 6325f757f3fSDimitry Andric break; 6335f757f3fSDimitry Andric case OpenACCDirectiveKind::Routine: { 6345f757f3fSDimitry Andric // Routine has an optional paren-wrapped name of a function in the local 6355f757f3fSDimitry Andric // scope. We parse the name, emitting any diagnostics 6365f757f3fSDimitry Andric ExprResult RoutineName = ParseOpenACCIDExpression(); 6375f757f3fSDimitry Andric // If the routine name is invalid, just skip until the closing paren to 6385f757f3fSDimitry Andric // recover more gracefully. 6395f757f3fSDimitry Andric if (RoutineName.isInvalid()) 6405f757f3fSDimitry Andric T.skipToEnd(); 6415f757f3fSDimitry Andric else 6425f757f3fSDimitry Andric T.consumeClose(); 6435f757f3fSDimitry Andric break; 6445f757f3fSDimitry Andric } 6455f757f3fSDimitry Andric case OpenACCDirectiveKind::Cache: 6465f757f3fSDimitry Andric ParseOpenACCCacheVarList(); 6475f757f3fSDimitry Andric // The ParseOpenACCCacheVarList function manages to recover from failures, 6485f757f3fSDimitry Andric // so we can always consume the close. 6495f757f3fSDimitry Andric T.consumeClose(); 6505f757f3fSDimitry Andric break; 6515f757f3fSDimitry Andric case OpenACCDirectiveKind::Wait: 6525f757f3fSDimitry Andric // OpenACC has an optional paren-wrapped 'wait-argument'. 6535f757f3fSDimitry Andric if (ParseOpenACCWaitArgument()) 6545f757f3fSDimitry Andric T.skipToEnd(); 6555f757f3fSDimitry Andric else 6565f757f3fSDimitry Andric T.consumeClose(); 6575f757f3fSDimitry Andric break; 6585f757f3fSDimitry Andric } 6595f757f3fSDimitry Andric } else if (DirKind == OpenACCDirectiveKind::Cache) { 6605f757f3fSDimitry Andric // Cache's paren var-list is required, so error here if it isn't provided. 6615f757f3fSDimitry Andric // We know that the consumeOpen above left the first non-paren here, so 6625f757f3fSDimitry Andric // diagnose, then continue as if it was completely omitted. 6635f757f3fSDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren; 6645f757f3fSDimitry Andric } 6655f757f3fSDimitry Andric 6665f757f3fSDimitry Andric // Parses the list of clauses, if present. 6675f757f3fSDimitry Andric ParseOpenACCClauseList(*this); 6685f757f3fSDimitry Andric 6695f757f3fSDimitry Andric Diag(getCurToken(), diag::warn_pragma_acc_unimplemented); 670cb14a3feSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc_end) && 671cb14a3feSDimitry Andric "Didn't parse all OpenACC Clauses"); 672cb14a3feSDimitry Andric ConsumeAnnotationToken(); 6735f757f3fSDimitry Andric } 6745f757f3fSDimitry Andric 6755f757f3fSDimitry Andric // Parse OpenACC directive on a declaration. 6765f757f3fSDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { 6775f757f3fSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 6785f757f3fSDimitry Andric 6795f757f3fSDimitry Andric ParsingOpenACCDirectiveRAII DirScope(*this); 6805f757f3fSDimitry Andric ConsumeAnnotationToken(); 6815f757f3fSDimitry Andric 6825f757f3fSDimitry Andric ParseOpenACCDirective(); 6835f757f3fSDimitry Andric 6845f757f3fSDimitry Andric return nullptr; 6855f757f3fSDimitry Andric } 6865f757f3fSDimitry Andric 6875f757f3fSDimitry Andric // Parse OpenACC Directive on a Statement. 6885f757f3fSDimitry Andric StmtResult Parser::ParseOpenACCDirectiveStmt() { 6895f757f3fSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 6905f757f3fSDimitry Andric 6915f757f3fSDimitry Andric ParsingOpenACCDirectiveRAII DirScope(*this); 6925f757f3fSDimitry Andric ConsumeAnnotationToken(); 6935f757f3fSDimitry Andric 6945f757f3fSDimitry Andric ParseOpenACCDirective(); 6955f757f3fSDimitry Andric 6965f757f3fSDimitry Andric return StmtEmpty(); 6975f757f3fSDimitry Andric } 698