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 13*0fca6ea1SDimitry Andric #include "clang/AST/OpenACCClause.h" 145f757f3fSDimitry Andric #include "clang/Basic/OpenACCKinds.h" 155f757f3fSDimitry Andric #include "clang/Parse/ParseDiagnostic.h" 165f757f3fSDimitry Andric #include "clang/Parse/Parser.h" 175f757f3fSDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h" 18*0fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenACC.h" 195f757f3fSDimitry Andric #include "llvm/ADT/StringRef.h" 205f757f3fSDimitry Andric #include "llvm/ADT/StringSwitch.h" 215f757f3fSDimitry Andric 225f757f3fSDimitry Andric using namespace clang; 235f757f3fSDimitry Andric using namespace llvm; 245f757f3fSDimitry Andric 255f757f3fSDimitry Andric namespace { 265f757f3fSDimitry Andric // An enum that contains the extended 'partial' parsed variants. This type 275f757f3fSDimitry Andric // should never escape the initial parse functionality, but is useful for 285f757f3fSDimitry Andric // simplifying the implementation. 295f757f3fSDimitry Andric enum class OpenACCDirectiveKindEx { 305f757f3fSDimitry Andric Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid), 315f757f3fSDimitry Andric // 'enter data' and 'exit data' 325f757f3fSDimitry Andric Enter, 335f757f3fSDimitry Andric Exit, 345f757f3fSDimitry Andric }; 355f757f3fSDimitry Andric 365f757f3fSDimitry Andric // Translate single-token string representations to the OpenACC Directive Kind. 375f757f3fSDimitry Andric // This doesn't completely comprehend 'Compound Constructs' (as it just 385f757f3fSDimitry Andric // identifies the first token), and doesn't fully handle 'enter data', 'exit 395f757f3fSDimitry Andric // data', nor any of the 'atomic' variants, just the first token of each. So 405f757f3fSDimitry Andric // this should only be used by `ParseOpenACCDirectiveKind`. 415f757f3fSDimitry Andric OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { 425f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 435f757f3fSDimitry Andric return OpenACCDirectiveKindEx::Invalid; 445f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = 455f757f3fSDimitry Andric llvm::StringSwitch<OpenACCDirectiveKind>( 465f757f3fSDimitry Andric Tok.getIdentifierInfo()->getName()) 475f757f3fSDimitry Andric .Case("parallel", OpenACCDirectiveKind::Parallel) 485f757f3fSDimitry Andric .Case("serial", OpenACCDirectiveKind::Serial) 495f757f3fSDimitry Andric .Case("kernels", OpenACCDirectiveKind::Kernels) 505f757f3fSDimitry Andric .Case("data", OpenACCDirectiveKind::Data) 515f757f3fSDimitry Andric .Case("host_data", OpenACCDirectiveKind::HostData) 525f757f3fSDimitry Andric .Case("loop", OpenACCDirectiveKind::Loop) 535f757f3fSDimitry Andric .Case("cache", OpenACCDirectiveKind::Cache) 545f757f3fSDimitry Andric .Case("atomic", OpenACCDirectiveKind::Atomic) 555f757f3fSDimitry Andric .Case("routine", OpenACCDirectiveKind::Routine) 565f757f3fSDimitry Andric .Case("declare", OpenACCDirectiveKind::Declare) 575f757f3fSDimitry Andric .Case("init", OpenACCDirectiveKind::Init) 585f757f3fSDimitry Andric .Case("shutdown", OpenACCDirectiveKind::Shutdown) 59*0fca6ea1SDimitry Andric .Case("set", OpenACCDirectiveKind::Set) 605f757f3fSDimitry Andric .Case("update", OpenACCDirectiveKind::Update) 615f757f3fSDimitry Andric .Case("wait", OpenACCDirectiveKind::Wait) 625f757f3fSDimitry Andric .Default(OpenACCDirectiveKind::Invalid); 635f757f3fSDimitry Andric 645f757f3fSDimitry Andric if (DirKind != OpenACCDirectiveKind::Invalid) 655f757f3fSDimitry Andric return static_cast<OpenACCDirectiveKindEx>(DirKind); 665f757f3fSDimitry Andric 675f757f3fSDimitry Andric return llvm::StringSwitch<OpenACCDirectiveKindEx>( 685f757f3fSDimitry Andric Tok.getIdentifierInfo()->getName()) 695f757f3fSDimitry Andric .Case("enter", OpenACCDirectiveKindEx::Enter) 705f757f3fSDimitry Andric .Case("exit", OpenACCDirectiveKindEx::Exit) 715f757f3fSDimitry Andric .Default(OpenACCDirectiveKindEx::Invalid); 725f757f3fSDimitry Andric } 735f757f3fSDimitry Andric 74cb14a3feSDimitry Andric // Translate single-token string representations to the OpenCC Clause Kind. 75cb14a3feSDimitry Andric OpenACCClauseKind getOpenACCClauseKind(Token Tok) { 76cb14a3feSDimitry Andric // auto is a keyword in some language modes, so make sure we parse it 77cb14a3feSDimitry Andric // correctly. 78cb14a3feSDimitry Andric if (Tok.is(tok::kw_auto)) 79cb14a3feSDimitry Andric return OpenACCClauseKind::Auto; 80cb14a3feSDimitry Andric 811db9f3b2SDimitry Andric // default is a keyword, so make sure we parse it correctly. 821db9f3b2SDimitry Andric if (Tok.is(tok::kw_default)) 831db9f3b2SDimitry Andric return OpenACCClauseKind::Default; 841db9f3b2SDimitry Andric 851db9f3b2SDimitry Andric // if is also a keyword, make sure we parse it correctly. 861db9f3b2SDimitry Andric if (Tok.is(tok::kw_if)) 871db9f3b2SDimitry Andric return OpenACCClauseKind::If; 881db9f3b2SDimitry Andric 89*0fca6ea1SDimitry Andric // 'private' is also a keyword, make sure we pare it correctly. 90*0fca6ea1SDimitry Andric if (Tok.is(tok::kw_private)) 91*0fca6ea1SDimitry Andric return OpenACCClauseKind::Private; 92*0fca6ea1SDimitry Andric 93cb14a3feSDimitry Andric if (!Tok.is(tok::identifier)) 94cb14a3feSDimitry Andric return OpenACCClauseKind::Invalid; 95cb14a3feSDimitry Andric 96cb14a3feSDimitry Andric return llvm::StringSwitch<OpenACCClauseKind>( 97cb14a3feSDimitry Andric Tok.getIdentifierInfo()->getName()) 98*0fca6ea1SDimitry Andric .Case("async", OpenACCClauseKind::Async) 997a6dacacSDimitry Andric .Case("attach", OpenACCClauseKind::Attach) 100cb14a3feSDimitry Andric .Case("auto", OpenACCClauseKind::Auto) 1017a6dacacSDimitry Andric .Case("bind", OpenACCClauseKind::Bind) 1027a6dacacSDimitry Andric .Case("create", OpenACCClauseKind::Create) 103*0fca6ea1SDimitry Andric .Case("pcreate", OpenACCClauseKind::PCreate) 104*0fca6ea1SDimitry Andric .Case("present_or_create", OpenACCClauseKind::PresentOrCreate) 1057a6dacacSDimitry Andric .Case("collapse", OpenACCClauseKind::Collapse) 1067a6dacacSDimitry Andric .Case("copy", OpenACCClauseKind::Copy) 107*0fca6ea1SDimitry Andric .Case("pcopy", OpenACCClauseKind::PCopy) 108*0fca6ea1SDimitry Andric .Case("present_or_copy", OpenACCClauseKind::PresentOrCopy) 1097a6dacacSDimitry Andric .Case("copyin", OpenACCClauseKind::CopyIn) 110*0fca6ea1SDimitry Andric .Case("pcopyin", OpenACCClauseKind::PCopyIn) 111*0fca6ea1SDimitry Andric .Case("present_or_copyin", OpenACCClauseKind::PresentOrCopyIn) 1127a6dacacSDimitry Andric .Case("copyout", OpenACCClauseKind::CopyOut) 113*0fca6ea1SDimitry Andric .Case("pcopyout", OpenACCClauseKind::PCopyOut) 114*0fca6ea1SDimitry Andric .Case("present_or_copyout", OpenACCClauseKind::PresentOrCopyOut) 1151db9f3b2SDimitry Andric .Case("default", OpenACCClauseKind::Default) 1167a6dacacSDimitry Andric .Case("default_async", OpenACCClauseKind::DefaultAsync) 1177a6dacacSDimitry Andric .Case("delete", OpenACCClauseKind::Delete) 1187a6dacacSDimitry Andric .Case("detach", OpenACCClauseKind::Detach) 1197a6dacacSDimitry Andric .Case("device", OpenACCClauseKind::Device) 1207a6dacacSDimitry Andric .Case("device_num", OpenACCClauseKind::DeviceNum) 1217a6dacacSDimitry Andric .Case("device_resident", OpenACCClauseKind::DeviceResident) 1227a6dacacSDimitry Andric .Case("device_type", OpenACCClauseKind::DeviceType) 1237a6dacacSDimitry Andric .Case("deviceptr", OpenACCClauseKind::DevicePtr) 1247a6dacacSDimitry Andric .Case("dtype", OpenACCClauseKind::DType) 125cb14a3feSDimitry Andric .Case("finalize", OpenACCClauseKind::Finalize) 1267a6dacacSDimitry Andric .Case("firstprivate", OpenACCClauseKind::FirstPrivate) 127*0fca6ea1SDimitry Andric .Case("gang", OpenACCClauseKind::Gang) 1287a6dacacSDimitry Andric .Case("host", OpenACCClauseKind::Host) 1291db9f3b2SDimitry Andric .Case("if", OpenACCClauseKind::If) 130cb14a3feSDimitry Andric .Case("if_present", OpenACCClauseKind::IfPresent) 131cb14a3feSDimitry Andric .Case("independent", OpenACCClauseKind::Independent) 1327a6dacacSDimitry Andric .Case("link", OpenACCClauseKind::Link) 1337a6dacacSDimitry Andric .Case("no_create", OpenACCClauseKind::NoCreate) 1347a6dacacSDimitry Andric .Case("num_gangs", OpenACCClauseKind::NumGangs) 1357a6dacacSDimitry Andric .Case("num_workers", OpenACCClauseKind::NumWorkers) 136cb14a3feSDimitry Andric .Case("nohost", OpenACCClauseKind::NoHost) 1377a6dacacSDimitry Andric .Case("present", OpenACCClauseKind::Present) 1387a6dacacSDimitry Andric .Case("private", OpenACCClauseKind::Private) 1397a6dacacSDimitry Andric .Case("reduction", OpenACCClauseKind::Reduction) 1401db9f3b2SDimitry Andric .Case("self", OpenACCClauseKind::Self) 141cb14a3feSDimitry Andric .Case("seq", OpenACCClauseKind::Seq) 142*0fca6ea1SDimitry Andric .Case("tile", OpenACCClauseKind::Tile) 1437a6dacacSDimitry Andric .Case("use_device", OpenACCClauseKind::UseDevice) 144cb14a3feSDimitry Andric .Case("vector", OpenACCClauseKind::Vector) 1457a6dacacSDimitry Andric .Case("vector_length", OpenACCClauseKind::VectorLength) 146*0fca6ea1SDimitry Andric .Case("wait", OpenACCClauseKind::Wait) 147cb14a3feSDimitry Andric .Case("worker", OpenACCClauseKind::Worker) 148cb14a3feSDimitry Andric .Default(OpenACCClauseKind::Invalid); 149cb14a3feSDimitry Andric } 150cb14a3feSDimitry Andric 1515f757f3fSDimitry Andric // Since 'atomic' is effectively a compound directive, this will decode the 1525f757f3fSDimitry Andric // second part of the directive. 1535f757f3fSDimitry Andric OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { 1545f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 1555f757f3fSDimitry Andric return OpenACCAtomicKind::Invalid; 1565f757f3fSDimitry Andric return llvm::StringSwitch<OpenACCAtomicKind>( 1575f757f3fSDimitry Andric Tok.getIdentifierInfo()->getName()) 1585f757f3fSDimitry Andric .Case("read", OpenACCAtomicKind::Read) 1595f757f3fSDimitry Andric .Case("write", OpenACCAtomicKind::Write) 1605f757f3fSDimitry Andric .Case("update", OpenACCAtomicKind::Update) 1615f757f3fSDimitry Andric .Case("capture", OpenACCAtomicKind::Capture) 1625f757f3fSDimitry Andric .Default(OpenACCAtomicKind::Invalid); 1635f757f3fSDimitry Andric } 1645f757f3fSDimitry Andric 1651db9f3b2SDimitry Andric OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) { 1661db9f3b2SDimitry Andric if (!Tok.is(tok::identifier)) 1671db9f3b2SDimitry Andric return OpenACCDefaultClauseKind::Invalid; 1681db9f3b2SDimitry Andric 1691db9f3b2SDimitry Andric return llvm::StringSwitch<OpenACCDefaultClauseKind>( 1701db9f3b2SDimitry Andric Tok.getIdentifierInfo()->getName()) 1711db9f3b2SDimitry Andric .Case("none", OpenACCDefaultClauseKind::None) 1721db9f3b2SDimitry Andric .Case("present", OpenACCDefaultClauseKind::Present) 1731db9f3b2SDimitry Andric .Default(OpenACCDefaultClauseKind::Invalid); 1741db9f3b2SDimitry Andric } 1751db9f3b2SDimitry Andric 1765f757f3fSDimitry Andric enum class OpenACCSpecialTokenKind { 1775f757f3fSDimitry Andric ReadOnly, 1785f757f3fSDimitry Andric DevNum, 1795f757f3fSDimitry Andric Queues, 1807a6dacacSDimitry Andric Zero, 1817a6dacacSDimitry Andric Force, 1827a6dacacSDimitry Andric Num, 1837a6dacacSDimitry Andric Length, 184*0fca6ea1SDimitry Andric Dim, 185*0fca6ea1SDimitry Andric Static, 1865f757f3fSDimitry Andric }; 1875f757f3fSDimitry Andric 1885f757f3fSDimitry Andric bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { 189*0fca6ea1SDimitry Andric if (Tok.is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static) 190*0fca6ea1SDimitry Andric return true; 191*0fca6ea1SDimitry Andric 1925f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 1935f757f3fSDimitry Andric return false; 1945f757f3fSDimitry Andric 1955f757f3fSDimitry Andric switch (Kind) { 1965f757f3fSDimitry Andric case OpenACCSpecialTokenKind::ReadOnly: 1975f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("readonly"); 1985f757f3fSDimitry Andric case OpenACCSpecialTokenKind::DevNum: 1995f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("devnum"); 2005f757f3fSDimitry Andric case OpenACCSpecialTokenKind::Queues: 2015f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("queues"); 2027a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Zero: 2037a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("zero"); 2047a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Force: 2057a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("force"); 2067a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Num: 2077a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("num"); 2087a6dacacSDimitry Andric case OpenACCSpecialTokenKind::Length: 2097a6dacacSDimitry Andric return Tok.getIdentifierInfo()->isStr("length"); 210*0fca6ea1SDimitry Andric case OpenACCSpecialTokenKind::Dim: 211*0fca6ea1SDimitry Andric return Tok.getIdentifierInfo()->isStr("dim"); 212*0fca6ea1SDimitry Andric case OpenACCSpecialTokenKind::Static: 213*0fca6ea1SDimitry Andric return Tok.getIdentifierInfo()->isStr("static"); 2145f757f3fSDimitry Andric } 2155f757f3fSDimitry Andric llvm_unreachable("Unknown 'Kind' Passed"); 2165f757f3fSDimitry Andric } 2175f757f3fSDimitry Andric 2187a6dacacSDimitry Andric /// Used for cases where we have a token we want to check against an 2197a6dacacSDimitry Andric /// 'identifier-like' token, but don't want to give awkward error messages in 2207a6dacacSDimitry Andric /// cases where it is accidentially a keyword. 2217a6dacacSDimitry Andric bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) { 2227a6dacacSDimitry Andric if (Tok.is(tok::identifier)) 2237a6dacacSDimitry Andric return true; 2247a6dacacSDimitry Andric 2257a6dacacSDimitry Andric if (!Tok.isAnnotation() && Tok.getIdentifierInfo() && 2267a6dacacSDimitry Andric Tok.getIdentifierInfo()->isKeyword(P.getLangOpts())) 2277a6dacacSDimitry Andric return true; 2287a6dacacSDimitry Andric 2297a6dacacSDimitry Andric return false; 2307a6dacacSDimitry Andric } 2317a6dacacSDimitry Andric 2327a6dacacSDimitry Andric /// Parses and consumes an identifer followed immediately by a single colon, and 2337a6dacacSDimitry Andric /// diagnoses if it is not the 'special token' kind that we require. Used when 2347a6dacacSDimitry Andric /// the tag is the only valid value. 2357a6dacacSDimitry Andric /// Return 'true' if the special token was matched, false if no special token, 2367a6dacacSDimitry Andric /// or an invalid special token was found. 2377a6dacacSDimitry Andric template <typename DirOrClauseTy> 2387a6dacacSDimitry Andric bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind, 2397a6dacacSDimitry Andric DirOrClauseTy DirOrClause) { 2407a6dacacSDimitry Andric Token IdentTok = P.getCurToken(); 2417a6dacacSDimitry Andric // If this is an identifier-like thing followed by ':', it is one of the 2427a6dacacSDimitry Andric // OpenACC 'special' name tags, so consume it. 2437a6dacacSDimitry Andric if (isTokenIdentifierOrKeyword(P, IdentTok) && P.NextToken().is(tok::colon)) { 2447a6dacacSDimitry Andric P.ConsumeToken(); 2457a6dacacSDimitry Andric P.ConsumeToken(); 2467a6dacacSDimitry Andric 2477a6dacacSDimitry Andric if (!isOpenACCSpecialToken(Kind, IdentTok)) { 2487a6dacacSDimitry Andric P.Diag(IdentTok, diag::err_acc_invalid_tag_kind) 2497a6dacacSDimitry Andric << IdentTok.getIdentifierInfo() << DirOrClause 2507a6dacacSDimitry Andric << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>; 2517a6dacacSDimitry Andric return false; 2527a6dacacSDimitry Andric } 2537a6dacacSDimitry Andric 2547a6dacacSDimitry Andric return true; 2557a6dacacSDimitry Andric } 2567a6dacacSDimitry Andric 2577a6dacacSDimitry Andric return false; 2587a6dacacSDimitry Andric } 2597a6dacacSDimitry Andric 2605f757f3fSDimitry Andric bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { 2615f757f3fSDimitry Andric if (!Tok.is(tok::identifier)) 2625f757f3fSDimitry Andric return false; 2635f757f3fSDimitry Andric 2645f757f3fSDimitry Andric switch (Kind) { 2655f757f3fSDimitry Andric case OpenACCDirectiveKind::Parallel: 2665f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("parallel"); 2675f757f3fSDimitry Andric case OpenACCDirectiveKind::Serial: 2685f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("serial"); 2695f757f3fSDimitry Andric case OpenACCDirectiveKind::Kernels: 2705f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("kernels"); 2715f757f3fSDimitry Andric case OpenACCDirectiveKind::Data: 2725f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("data"); 2735f757f3fSDimitry Andric case OpenACCDirectiveKind::HostData: 2745f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("host_data"); 2755f757f3fSDimitry Andric case OpenACCDirectiveKind::Loop: 2765f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("loop"); 2775f757f3fSDimitry Andric case OpenACCDirectiveKind::Cache: 2785f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("cache"); 2795f757f3fSDimitry Andric 2805f757f3fSDimitry Andric case OpenACCDirectiveKind::ParallelLoop: 2815f757f3fSDimitry Andric case OpenACCDirectiveKind::SerialLoop: 2825f757f3fSDimitry Andric case OpenACCDirectiveKind::KernelsLoop: 2835f757f3fSDimitry Andric case OpenACCDirectiveKind::EnterData: 2845f757f3fSDimitry Andric case OpenACCDirectiveKind::ExitData: 2855f757f3fSDimitry Andric return false; 2865f757f3fSDimitry Andric 2875f757f3fSDimitry Andric case OpenACCDirectiveKind::Atomic: 2885f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("atomic"); 2895f757f3fSDimitry Andric case OpenACCDirectiveKind::Routine: 2905f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("routine"); 2915f757f3fSDimitry Andric case OpenACCDirectiveKind::Declare: 2925f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("declare"); 2935f757f3fSDimitry Andric case OpenACCDirectiveKind::Init: 2945f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("init"); 2955f757f3fSDimitry Andric case OpenACCDirectiveKind::Shutdown: 2965f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("shutdown"); 2975f757f3fSDimitry Andric case OpenACCDirectiveKind::Set: 2985f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("set"); 2995f757f3fSDimitry Andric case OpenACCDirectiveKind::Update: 3005f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("update"); 3015f757f3fSDimitry Andric case OpenACCDirectiveKind::Wait: 3025f757f3fSDimitry Andric return Tok.getIdentifierInfo()->isStr("wait"); 3035f757f3fSDimitry Andric case OpenACCDirectiveKind::Invalid: 3045f757f3fSDimitry Andric return false; 3055f757f3fSDimitry Andric } 3065f757f3fSDimitry Andric llvm_unreachable("Unknown 'Kind' Passed"); 3075f757f3fSDimitry Andric } 3085f757f3fSDimitry Andric 3097a6dacacSDimitry Andric OpenACCReductionOperator ParseReductionOperator(Parser &P) { 3107a6dacacSDimitry Andric // If there is no colon, treat as if the reduction operator was missing, else 3117a6dacacSDimitry Andric // we probably will not recover from it in the case where an expression starts 3127a6dacacSDimitry Andric // with one of the operator tokens. 3137a6dacacSDimitry Andric if (P.NextToken().isNot(tok::colon)) { 3147a6dacacSDimitry Andric P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator); 3157a6dacacSDimitry Andric return OpenACCReductionOperator::Invalid; 3167a6dacacSDimitry Andric } 3177a6dacacSDimitry Andric Token ReductionKindTok = P.getCurToken(); 3187a6dacacSDimitry Andric // Consume both the kind and the colon. 3197a6dacacSDimitry Andric P.ConsumeToken(); 3207a6dacacSDimitry Andric P.ConsumeToken(); 3217a6dacacSDimitry Andric 3227a6dacacSDimitry Andric switch (ReductionKindTok.getKind()) { 3237a6dacacSDimitry Andric case tok::plus: 3247a6dacacSDimitry Andric return OpenACCReductionOperator::Addition; 3257a6dacacSDimitry Andric case tok::star: 3267a6dacacSDimitry Andric return OpenACCReductionOperator::Multiplication; 3277a6dacacSDimitry Andric case tok::amp: 3287a6dacacSDimitry Andric return OpenACCReductionOperator::BitwiseAnd; 3297a6dacacSDimitry Andric case tok::pipe: 3307a6dacacSDimitry Andric return OpenACCReductionOperator::BitwiseOr; 3317a6dacacSDimitry Andric case tok::caret: 3327a6dacacSDimitry Andric return OpenACCReductionOperator::BitwiseXOr; 3337a6dacacSDimitry Andric case tok::ampamp: 3347a6dacacSDimitry Andric return OpenACCReductionOperator::And; 3357a6dacacSDimitry Andric case tok::pipepipe: 3367a6dacacSDimitry Andric return OpenACCReductionOperator::Or; 3377a6dacacSDimitry Andric case tok::identifier: 3387a6dacacSDimitry Andric if (ReductionKindTok.getIdentifierInfo()->isStr("max")) 3397a6dacacSDimitry Andric return OpenACCReductionOperator::Max; 3407a6dacacSDimitry Andric if (ReductionKindTok.getIdentifierInfo()->isStr("min")) 3417a6dacacSDimitry Andric return OpenACCReductionOperator::Min; 342*0fca6ea1SDimitry Andric [[fallthrough]]; 3437a6dacacSDimitry Andric default: 3447a6dacacSDimitry Andric P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator); 3457a6dacacSDimitry Andric return OpenACCReductionOperator::Invalid; 3467a6dacacSDimitry Andric } 3477a6dacacSDimitry Andric llvm_unreachable("Reduction op token kind not caught by 'default'?"); 3487a6dacacSDimitry Andric } 3497a6dacacSDimitry Andric 3501db9f3b2SDimitry Andric /// Used for cases where we expect an identifier-like token, but don't want to 3511db9f3b2SDimitry Andric /// give awkward error messages in cases where it is accidentially a keyword. 3521db9f3b2SDimitry Andric bool expectIdentifierOrKeyword(Parser &P) { 3531db9f3b2SDimitry Andric Token Tok = P.getCurToken(); 3541db9f3b2SDimitry Andric 3557a6dacacSDimitry Andric if (isTokenIdentifierOrKeyword(P, Tok)) 3561db9f3b2SDimitry Andric return false; 3571db9f3b2SDimitry Andric 3581db9f3b2SDimitry Andric P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier; 3591db9f3b2SDimitry Andric return true; 3601db9f3b2SDimitry Andric } 3611db9f3b2SDimitry Andric 3625f757f3fSDimitry Andric OpenACCDirectiveKind 3635f757f3fSDimitry Andric ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok, 3645f757f3fSDimitry Andric OpenACCDirectiveKindEx ExtDirKind) { 3655f757f3fSDimitry Andric Token SecondTok = P.getCurToken(); 3665f757f3fSDimitry Andric 3675f757f3fSDimitry Andric if (SecondTok.isAnnotation()) { 3685f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 3695f757f3fSDimitry Andric << 0 << FirstTok.getIdentifierInfo(); 3705f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 3715f757f3fSDimitry Andric } 3725f757f3fSDimitry Andric 373cb14a3feSDimitry Andric // Consume the second name anyway, this way we can continue on without making 374cb14a3feSDimitry Andric // this oddly look like a clause. 375cb14a3feSDimitry Andric P.ConsumeAnyToken(); 376cb14a3feSDimitry Andric 3775f757f3fSDimitry Andric if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) { 3785f757f3fSDimitry Andric if (!SecondTok.is(tok::identifier)) 3795f757f3fSDimitry Andric P.Diag(SecondTok, diag::err_expected) << tok::identifier; 3805f757f3fSDimitry Andric else 3815f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 3825f757f3fSDimitry Andric << 1 << FirstTok.getIdentifierInfo()->getName() 3835f757f3fSDimitry Andric << SecondTok.getIdentifierInfo()->getName(); 3845f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 3855f757f3fSDimitry Andric } 3865f757f3fSDimitry Andric 3875f757f3fSDimitry Andric return ExtDirKind == OpenACCDirectiveKindEx::Enter 3885f757f3fSDimitry Andric ? OpenACCDirectiveKind::EnterData 3895f757f3fSDimitry Andric : OpenACCDirectiveKind::ExitData; 3905f757f3fSDimitry Andric } 3915f757f3fSDimitry Andric 3925f757f3fSDimitry Andric OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) { 3935f757f3fSDimitry Andric Token AtomicClauseToken = P.getCurToken(); 3945f757f3fSDimitry Andric 3955f757f3fSDimitry Andric // #pragma acc atomic is equivilent to update: 3965f757f3fSDimitry Andric if (AtomicClauseToken.isAnnotation()) 3975f757f3fSDimitry Andric return OpenACCAtomicKind::Update; 3985f757f3fSDimitry Andric 3995f757f3fSDimitry Andric OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken); 4005f757f3fSDimitry Andric 4015f757f3fSDimitry Andric // If we don't know what this is, treat it as 'nothing', and treat the rest of 4025f757f3fSDimitry Andric // this as a clause list, which, despite being invalid, is likely what the 4035f757f3fSDimitry Andric // user was trying to do. 4045f757f3fSDimitry Andric if (AtomicKind == OpenACCAtomicKind::Invalid) 4055f757f3fSDimitry Andric return OpenACCAtomicKind::Update; 4065f757f3fSDimitry Andric 4075f757f3fSDimitry Andric P.ConsumeToken(); 4085f757f3fSDimitry Andric return AtomicKind; 4095f757f3fSDimitry Andric } 4105f757f3fSDimitry Andric 4115f757f3fSDimitry Andric // Parse and consume the tokens for OpenACC Directive/Construct kinds. 4125f757f3fSDimitry Andric OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { 4135f757f3fSDimitry Andric Token FirstTok = P.getCurToken(); 4145f757f3fSDimitry Andric 4155f757f3fSDimitry Andric // Just #pragma acc can get us immediately to the end, make sure we don't 4165f757f3fSDimitry Andric // introspect on the spelling before then. 4175f757f3fSDimitry Andric if (FirstTok.isNot(tok::identifier)) { 4185f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_missing_directive); 419cb14a3feSDimitry Andric 420cb14a3feSDimitry Andric if (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 421cb14a3feSDimitry Andric P.ConsumeAnyToken(); 422cb14a3feSDimitry Andric 4235f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 4245f757f3fSDimitry Andric } 4255f757f3fSDimitry Andric 4265f757f3fSDimitry Andric P.ConsumeToken(); 4275f757f3fSDimitry Andric 4285f757f3fSDimitry Andric OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok); 4295f757f3fSDimitry Andric 4305f757f3fSDimitry Andric // OpenACCDirectiveKindEx is meant to be an extended list 4315f757f3fSDimitry Andric // over OpenACCDirectiveKind, so any value below Invalid is one of the 4325f757f3fSDimitry Andric // OpenACCDirectiveKind values. This switch takes care of all of the extra 4335f757f3fSDimitry Andric // parsing required for the Extended values. At the end of this block, 4345f757f3fSDimitry Andric // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can 4355f757f3fSDimitry Andric // immediately cast it and use it as that. 4365f757f3fSDimitry Andric if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) { 4375f757f3fSDimitry Andric switch (ExDirKind) { 4385f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Invalid: { 4395f757f3fSDimitry Andric P.Diag(FirstTok, diag::err_acc_invalid_directive) 4405f757f3fSDimitry Andric << 0 << FirstTok.getIdentifierInfo(); 4415f757f3fSDimitry Andric return OpenACCDirectiveKind::Invalid; 4425f757f3fSDimitry Andric } 4435f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Enter: 4445f757f3fSDimitry Andric case OpenACCDirectiveKindEx::Exit: 4455f757f3fSDimitry Andric return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind); 4465f757f3fSDimitry Andric } 4475f757f3fSDimitry Andric } 4485f757f3fSDimitry Andric 4495f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind); 4505f757f3fSDimitry Andric 4515f757f3fSDimitry Andric // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any 4525f757f3fSDimitry Andric // other attempt at a combined construct will be diagnosed as an invalid 4535f757f3fSDimitry Andric // clause. 4545f757f3fSDimitry Andric Token SecondTok = P.getCurToken(); 4555f757f3fSDimitry Andric if (!SecondTok.isAnnotation() && 4565f757f3fSDimitry Andric isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) { 4575f757f3fSDimitry Andric switch (DirKind) { 4585f757f3fSDimitry Andric default: 4595f757f3fSDimitry Andric // Nothing to do except in the below cases, as they should be diagnosed as 4605f757f3fSDimitry Andric // a clause. 4615f757f3fSDimitry Andric break; 4625f757f3fSDimitry Andric case OpenACCDirectiveKind::Parallel: 4635f757f3fSDimitry Andric P.ConsumeToken(); 4645f757f3fSDimitry Andric return OpenACCDirectiveKind::ParallelLoop; 4655f757f3fSDimitry Andric case OpenACCDirectiveKind::Serial: 4665f757f3fSDimitry Andric P.ConsumeToken(); 4675f757f3fSDimitry Andric return OpenACCDirectiveKind::SerialLoop; 4685f757f3fSDimitry Andric case OpenACCDirectiveKind::Kernels: 4695f757f3fSDimitry Andric P.ConsumeToken(); 4705f757f3fSDimitry Andric return OpenACCDirectiveKind::KernelsLoop; 4715f757f3fSDimitry Andric } 4725f757f3fSDimitry Andric } 4735f757f3fSDimitry Andric 4745f757f3fSDimitry Andric return DirKind; 4755f757f3fSDimitry Andric } 4765f757f3fSDimitry Andric 4777a6dacacSDimitry Andric enum ClauseParensKind { 4787a6dacacSDimitry Andric None, 4797a6dacacSDimitry Andric Optional, 4807a6dacacSDimitry Andric Required 4817a6dacacSDimitry Andric }; 4827a6dacacSDimitry Andric 4837a6dacacSDimitry Andric ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind, 4847a6dacacSDimitry Andric OpenACCClauseKind Kind) { 4857a6dacacSDimitry Andric switch (Kind) { 4867a6dacacSDimitry Andric case OpenACCClauseKind::Self: 4877a6dacacSDimitry Andric return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required 4887a6dacacSDimitry Andric : ClauseParensKind::Optional; 489*0fca6ea1SDimitry Andric case OpenACCClauseKind::Async: 4907a6dacacSDimitry Andric case OpenACCClauseKind::Worker: 4917a6dacacSDimitry Andric case OpenACCClauseKind::Vector: 492*0fca6ea1SDimitry Andric case OpenACCClauseKind::Gang: 493*0fca6ea1SDimitry Andric case OpenACCClauseKind::Wait: 4947a6dacacSDimitry Andric return ClauseParensKind::Optional; 4957a6dacacSDimitry Andric 4967a6dacacSDimitry Andric case OpenACCClauseKind::Default: 4977a6dacacSDimitry Andric case OpenACCClauseKind::If: 4987a6dacacSDimitry Andric case OpenACCClauseKind::Create: 499*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCreate: 500*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCreate: 5017a6dacacSDimitry Andric case OpenACCClauseKind::Copy: 502*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCopy: 503*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCopy: 5047a6dacacSDimitry Andric case OpenACCClauseKind::CopyIn: 505*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCopyIn: 506*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCopyIn: 5077a6dacacSDimitry Andric case OpenACCClauseKind::CopyOut: 508*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCopyOut: 509*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCopyOut: 5107a6dacacSDimitry Andric case OpenACCClauseKind::UseDevice: 5117a6dacacSDimitry Andric case OpenACCClauseKind::NoCreate: 5127a6dacacSDimitry Andric case OpenACCClauseKind::Present: 5137a6dacacSDimitry Andric case OpenACCClauseKind::DevicePtr: 5147a6dacacSDimitry Andric case OpenACCClauseKind::Attach: 5157a6dacacSDimitry Andric case OpenACCClauseKind::Detach: 5167a6dacacSDimitry Andric case OpenACCClauseKind::Private: 5177a6dacacSDimitry Andric case OpenACCClauseKind::FirstPrivate: 5187a6dacacSDimitry Andric case OpenACCClauseKind::Delete: 5197a6dacacSDimitry Andric case OpenACCClauseKind::DeviceResident: 5207a6dacacSDimitry Andric case OpenACCClauseKind::Device: 5217a6dacacSDimitry Andric case OpenACCClauseKind::Link: 5227a6dacacSDimitry Andric case OpenACCClauseKind::Host: 5237a6dacacSDimitry Andric case OpenACCClauseKind::Reduction: 5247a6dacacSDimitry Andric case OpenACCClauseKind::Collapse: 5257a6dacacSDimitry Andric case OpenACCClauseKind::Bind: 5267a6dacacSDimitry Andric case OpenACCClauseKind::VectorLength: 5277a6dacacSDimitry Andric case OpenACCClauseKind::NumGangs: 5287a6dacacSDimitry Andric case OpenACCClauseKind::NumWorkers: 5297a6dacacSDimitry Andric case OpenACCClauseKind::DeviceNum: 5307a6dacacSDimitry Andric case OpenACCClauseKind::DefaultAsync: 5317a6dacacSDimitry Andric case OpenACCClauseKind::DeviceType: 5327a6dacacSDimitry Andric case OpenACCClauseKind::DType: 533*0fca6ea1SDimitry Andric case OpenACCClauseKind::Tile: 5347a6dacacSDimitry Andric return ClauseParensKind::Required; 5357a6dacacSDimitry Andric 5367a6dacacSDimitry Andric case OpenACCClauseKind::Auto: 5377a6dacacSDimitry Andric case OpenACCClauseKind::Finalize: 5387a6dacacSDimitry Andric case OpenACCClauseKind::IfPresent: 5397a6dacacSDimitry Andric case OpenACCClauseKind::Independent: 5407a6dacacSDimitry Andric case OpenACCClauseKind::Invalid: 5417a6dacacSDimitry Andric case OpenACCClauseKind::NoHost: 5427a6dacacSDimitry Andric case OpenACCClauseKind::Seq: 5437a6dacacSDimitry Andric return ClauseParensKind::None; 5447a6dacacSDimitry Andric } 5457a6dacacSDimitry Andric llvm_unreachable("Unhandled clause kind"); 5461db9f3b2SDimitry Andric } 5471db9f3b2SDimitry Andric 5487a6dacacSDimitry Andric bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind, 5497a6dacacSDimitry Andric OpenACCClauseKind Kind) { 5507a6dacacSDimitry Andric return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional; 5517a6dacacSDimitry Andric } 5527a6dacacSDimitry Andric 5537a6dacacSDimitry Andric bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind, 5547a6dacacSDimitry Andric OpenACCClauseKind Kind) { 5557a6dacacSDimitry Andric return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required; 5561db9f3b2SDimitry Andric } 5571db9f3b2SDimitry Andric 558cb14a3feSDimitry Andric // Skip until we see the end of pragma token, but don't consume it. This is us 559cb14a3feSDimitry Andric // just giving up on the rest of the pragma so we can continue executing. We 560cb14a3feSDimitry Andric // have to do this because 'SkipUntil' considers paren balancing, which isn't 561cb14a3feSDimitry Andric // what we want. 562cb14a3feSDimitry Andric void SkipUntilEndOfDirective(Parser &P) { 563cb14a3feSDimitry Andric while (P.getCurToken().isNot(tok::annot_pragma_openacc_end)) 564cb14a3feSDimitry Andric P.ConsumeAnyToken(); 565cb14a3feSDimitry Andric } 566cb14a3feSDimitry Andric 567*0fca6ea1SDimitry Andric bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) { 568*0fca6ea1SDimitry Andric switch (DirKind) { 569*0fca6ea1SDimitry Andric default: 570*0fca6ea1SDimitry Andric return false; 571*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Parallel: 572*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Serial: 573*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Kernels: 574*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Loop: 575*0fca6ea1SDimitry Andric return true; 576*0fca6ea1SDimitry Andric } 577*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled directive->assoc stmt"); 578*0fca6ea1SDimitry Andric } 579*0fca6ea1SDimitry Andric 580*0fca6ea1SDimitry Andric unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) { 581*0fca6ea1SDimitry Andric switch (DirKind) { 582*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Parallel: 583*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Serial: 584*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Kernels: 585*0fca6ea1SDimitry Andric // Mark this as a BreakScope/ContinueScope as well as a compute construct 586*0fca6ea1SDimitry Andric // so that we can diagnose trying to 'break'/'continue' inside of one. 587*0fca6ea1SDimitry Andric return Scope::BreakScope | Scope::ContinueScope | 588*0fca6ea1SDimitry Andric Scope::OpenACCComputeConstructScope; 589*0fca6ea1SDimitry Andric case OpenACCDirectiveKind::Invalid: 590*0fca6ea1SDimitry Andric llvm_unreachable("Shouldn't be creating a scope for an invalid construct"); 591*0fca6ea1SDimitry Andric default: 592*0fca6ea1SDimitry Andric break; 593*0fca6ea1SDimitry Andric } 594*0fca6ea1SDimitry Andric return 0; 595*0fca6ea1SDimitry Andric } 596*0fca6ea1SDimitry Andric 5977a6dacacSDimitry Andric } // namespace 5987a6dacacSDimitry Andric 599*0fca6ea1SDimitry Andric Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() { 600*0fca6ea1SDimitry Andric return {nullptr, OpenACCParseCanContinue::Can}; 601*0fca6ea1SDimitry Andric } 602*0fca6ea1SDimitry Andric 603*0fca6ea1SDimitry Andric Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() { 604*0fca6ea1SDimitry Andric return {nullptr, OpenACCParseCanContinue::Cannot}; 605*0fca6ea1SDimitry Andric } 606*0fca6ea1SDimitry Andric 607*0fca6ea1SDimitry Andric Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) { 608*0fca6ea1SDimitry Andric return {Clause, OpenACCParseCanContinue::Can}; 609*0fca6ea1SDimitry Andric } 610*0fca6ea1SDimitry Andric 611*0fca6ea1SDimitry Andric ExprResult Parser::ParseOpenACCConditionExpr() { 612*0fca6ea1SDimitry Andric // FIXME: It isn't clear if the spec saying 'condition' means the same as 613*0fca6ea1SDimitry Andric // it does in an if/while/etc (See ParseCXXCondition), however as it was 614*0fca6ea1SDimitry Andric // written with Fortran/C in mind, we're going to assume it just means an 615*0fca6ea1SDimitry Andric // 'expression evaluating to boolean'. 616*0fca6ea1SDimitry Andric ExprResult ER = getActions().CorrectDelayedTyposInExpr(ParseExpression()); 617*0fca6ea1SDimitry Andric 618*0fca6ea1SDimitry Andric if (!ER.isUsable()) 619*0fca6ea1SDimitry Andric return ER; 620*0fca6ea1SDimitry Andric 621*0fca6ea1SDimitry Andric Sema::ConditionResult R = 622*0fca6ea1SDimitry Andric getActions().ActOnCondition(getCurScope(), ER.get()->getExprLoc(), 623*0fca6ea1SDimitry Andric ER.get(), Sema::ConditionKind::Boolean); 624*0fca6ea1SDimitry Andric 625*0fca6ea1SDimitry Andric return R.isInvalid() ? ExprError() : R.get().second; 626*0fca6ea1SDimitry Andric } 627*0fca6ea1SDimitry Andric 628cb14a3feSDimitry Andric // OpenACC 3.3, section 1.7: 629cb14a3feSDimitry Andric // To simplify the specification and convey appropriate constraint information, 630cb14a3feSDimitry Andric // a pqr-list is a comma-separated list of pdr items. The one exception is a 631cb14a3feSDimitry Andric // clause-list, which is a list of one or more clauses optionally separated by 632cb14a3feSDimitry Andric // commas. 633*0fca6ea1SDimitry Andric SmallVector<OpenACCClause *> 634*0fca6ea1SDimitry Andric Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { 635*0fca6ea1SDimitry Andric SmallVector<OpenACCClause *> Clauses; 636cb14a3feSDimitry Andric bool FirstClause = true; 6377a6dacacSDimitry Andric while (getCurToken().isNot(tok::annot_pragma_openacc_end)) { 638cb14a3feSDimitry Andric // Comma is optional in a clause-list. 6397a6dacacSDimitry Andric if (!FirstClause && getCurToken().is(tok::comma)) 6407a6dacacSDimitry Andric ConsumeToken(); 641cb14a3feSDimitry Andric FirstClause = false; 642cb14a3feSDimitry Andric 643*0fca6ea1SDimitry Andric OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind); 644*0fca6ea1SDimitry Andric if (OpenACCClause *Clause = Result.getPointer()) { 645*0fca6ea1SDimitry Andric Clauses.push_back(Clause); 646*0fca6ea1SDimitry Andric } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) { 647cb14a3feSDimitry Andric // Recovering from a bad clause is really difficult, so we just give up on 648cb14a3feSDimitry Andric // error. 6497a6dacacSDimitry Andric SkipUntilEndOfDirective(*this); 650*0fca6ea1SDimitry Andric return Clauses; 651cb14a3feSDimitry Andric } 652cb14a3feSDimitry Andric } 653*0fca6ea1SDimitry Andric return Clauses; 6545f757f3fSDimitry Andric } 6555f757f3fSDimitry Andric 656*0fca6ea1SDimitry Andric Parser::OpenACCIntExprParseResult 657*0fca6ea1SDimitry Andric Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, 658*0fca6ea1SDimitry Andric SourceLocation Loc) { 659*0fca6ea1SDimitry Andric ExprResult ER = ParseAssignmentExpression(); 660*0fca6ea1SDimitry Andric 661*0fca6ea1SDimitry Andric // If the actual parsing failed, we don't know the state of the parse, so 662*0fca6ea1SDimitry Andric // don't try to continue. 663*0fca6ea1SDimitry Andric if (!ER.isUsable()) 664*0fca6ea1SDimitry Andric return {ER, OpenACCParseCanContinue::Cannot}; 665*0fca6ea1SDimitry Andric 666*0fca6ea1SDimitry Andric // Parsing can continue after the initial assignment expression parsing, so 667*0fca6ea1SDimitry Andric // even if there was a typo, we can continue. 668*0fca6ea1SDimitry Andric ER = getActions().CorrectDelayedTyposInExpr(ER); 669*0fca6ea1SDimitry Andric if (!ER.isUsable()) 670*0fca6ea1SDimitry Andric return {ER, OpenACCParseCanContinue::Can}; 671*0fca6ea1SDimitry Andric 672*0fca6ea1SDimitry Andric return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()), 673*0fca6ea1SDimitry Andric OpenACCParseCanContinue::Can}; 6747a6dacacSDimitry Andric } 6757a6dacacSDimitry Andric 676*0fca6ea1SDimitry Andric bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK, 677*0fca6ea1SDimitry Andric OpenACCClauseKind CK, SourceLocation Loc, 678*0fca6ea1SDimitry Andric llvm::SmallVectorImpl<Expr *> &IntExprs) { 679*0fca6ea1SDimitry Andric OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc); 6807a6dacacSDimitry Andric 681*0fca6ea1SDimitry Andric if (!CurResult.first.isUsable() && 682*0fca6ea1SDimitry Andric CurResult.second == OpenACCParseCanContinue::Cannot) { 683*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 684*0fca6ea1SDimitry Andric Parser::StopBeforeMatch); 6857a6dacacSDimitry Andric return true; 686*0fca6ea1SDimitry Andric } 687*0fca6ea1SDimitry Andric 688*0fca6ea1SDimitry Andric IntExprs.push_back(CurResult.first.get()); 6897a6dacacSDimitry Andric 6907a6dacacSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 6917a6dacacSDimitry Andric ExpectAndConsume(tok::comma); 6927a6dacacSDimitry Andric 693*0fca6ea1SDimitry Andric CurResult = ParseOpenACCIntExpr(DK, CK, Loc); 694*0fca6ea1SDimitry Andric 695*0fca6ea1SDimitry Andric if (!CurResult.first.isUsable() && 696*0fca6ea1SDimitry Andric CurResult.second == OpenACCParseCanContinue::Cannot) { 697*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 698*0fca6ea1SDimitry Andric Parser::StopBeforeMatch); 6997a6dacacSDimitry Andric return true; 7007a6dacacSDimitry Andric } 701*0fca6ea1SDimitry Andric IntExprs.push_back(CurResult.first.get()); 702*0fca6ea1SDimitry Andric } 7037a6dacacSDimitry Andric return false; 7047a6dacacSDimitry Andric } 7057a6dacacSDimitry Andric 7067a6dacacSDimitry Andric /// OpenACC 3.3 Section 2.4: 7077a6dacacSDimitry Andric /// The argument to the device_type clause is a comma-separated list of one or 7087a6dacacSDimitry Andric /// more device architecture name identifiers, or an asterisk. 7097a6dacacSDimitry Andric /// 7107a6dacacSDimitry Andric /// The syntax of the device_type clause is 7117a6dacacSDimitry Andric /// device_type( * ) 7127a6dacacSDimitry Andric /// device_type( device-type-list ) 7137a6dacacSDimitry Andric /// 7147a6dacacSDimitry Andric /// The device_type clause may be abbreviated to dtype. 715*0fca6ea1SDimitry Andric bool Parser::ParseOpenACCDeviceTypeList( 716*0fca6ea1SDimitry Andric llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs) { 7177a6dacacSDimitry Andric 7187a6dacacSDimitry Andric if (expectIdentifierOrKeyword(*this)) { 7197a6dacacSDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 7207a6dacacSDimitry Andric Parser::StopBeforeMatch); 721*0fca6ea1SDimitry Andric return true; 7227a6dacacSDimitry Andric } 723*0fca6ea1SDimitry Andric IdentifierInfo *Ident = getCurToken().getIdentifierInfo(); 724*0fca6ea1SDimitry Andric Archs.emplace_back(Ident, ConsumeToken()); 7257a6dacacSDimitry Andric 7267a6dacacSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 7277a6dacacSDimitry Andric ExpectAndConsume(tok::comma); 7287a6dacacSDimitry Andric 7297a6dacacSDimitry Andric if (expectIdentifierOrKeyword(*this)) { 7307a6dacacSDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 7317a6dacacSDimitry Andric Parser::StopBeforeMatch); 732*0fca6ea1SDimitry Andric return true; 733*0fca6ea1SDimitry Andric } 734*0fca6ea1SDimitry Andric Ident = getCurToken().getIdentifierInfo(); 735*0fca6ea1SDimitry Andric Archs.emplace_back(Ident, ConsumeToken()); 736*0fca6ea1SDimitry Andric } 7377a6dacacSDimitry Andric return false; 7387a6dacacSDimitry Andric } 739*0fca6ea1SDimitry Andric 740*0fca6ea1SDimitry Andric /// OpenACC 3.3 Section 2.9: 741*0fca6ea1SDimitry Andric /// size-expr is one of: 742*0fca6ea1SDimitry Andric // * 743*0fca6ea1SDimitry Andric // int-expr 744*0fca6ea1SDimitry Andric // Note that this is specified under 'gang-arg-list', but also applies to 'tile' 745*0fca6ea1SDimitry Andric // via reference. 746*0fca6ea1SDimitry Andric bool Parser::ParseOpenACCSizeExpr() { 747*0fca6ea1SDimitry Andric // FIXME: Ensure these are constant expressions. 748*0fca6ea1SDimitry Andric 749*0fca6ea1SDimitry Andric // The size-expr ends up being ambiguous when only looking at the current 750*0fca6ea1SDimitry Andric // token, as it could be a deref of a variable/expression. 751*0fca6ea1SDimitry Andric if (getCurToken().is(tok::star) && 752*0fca6ea1SDimitry Andric NextToken().isOneOf(tok::comma, tok::r_paren, 753*0fca6ea1SDimitry Andric tok::annot_pragma_openacc_end)) { 7547a6dacacSDimitry Andric ConsumeToken(); 755*0fca6ea1SDimitry Andric return false; 756*0fca6ea1SDimitry Andric } 757*0fca6ea1SDimitry Andric 758*0fca6ea1SDimitry Andric return getActions() 759*0fca6ea1SDimitry Andric .CorrectDelayedTyposInExpr(ParseAssignmentExpression()) 760*0fca6ea1SDimitry Andric .isInvalid(); 761*0fca6ea1SDimitry Andric } 762*0fca6ea1SDimitry Andric 763*0fca6ea1SDimitry Andric bool Parser::ParseOpenACCSizeExprList() { 764*0fca6ea1SDimitry Andric if (ParseOpenACCSizeExpr()) { 765*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 766*0fca6ea1SDimitry Andric Parser::StopBeforeMatch); 767*0fca6ea1SDimitry Andric return false; 768*0fca6ea1SDimitry Andric } 769*0fca6ea1SDimitry Andric 770*0fca6ea1SDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 771*0fca6ea1SDimitry Andric ExpectAndConsume(tok::comma); 772*0fca6ea1SDimitry Andric 773*0fca6ea1SDimitry Andric if (ParseOpenACCSizeExpr()) { 774*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 775*0fca6ea1SDimitry Andric Parser::StopBeforeMatch); 776*0fca6ea1SDimitry Andric return false; 777*0fca6ea1SDimitry Andric } 778*0fca6ea1SDimitry Andric } 779*0fca6ea1SDimitry Andric return false; 780*0fca6ea1SDimitry Andric } 781*0fca6ea1SDimitry Andric 782*0fca6ea1SDimitry Andric /// OpenACC 3.3 Section 2.9: 783*0fca6ea1SDimitry Andric /// 784*0fca6ea1SDimitry Andric /// where gang-arg is one of: 785*0fca6ea1SDimitry Andric /// [num:]int-expr 786*0fca6ea1SDimitry Andric /// dim:int-expr 787*0fca6ea1SDimitry Andric /// static:size-expr 788*0fca6ea1SDimitry Andric bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) { 789*0fca6ea1SDimitry Andric 790*0fca6ea1SDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) && 791*0fca6ea1SDimitry Andric NextToken().is(tok::colon)) { 792*0fca6ea1SDimitry Andric // 'static' just takes a size-expr, which is an int-expr or an asterisk. 793*0fca6ea1SDimitry Andric ConsumeToken(); 794*0fca6ea1SDimitry Andric ConsumeToken(); 795*0fca6ea1SDimitry Andric return ParseOpenACCSizeExpr(); 796*0fca6ea1SDimitry Andric } 797*0fca6ea1SDimitry Andric 798*0fca6ea1SDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) && 799*0fca6ea1SDimitry Andric NextToken().is(tok::colon)) { 800*0fca6ea1SDimitry Andric ConsumeToken(); 801*0fca6ea1SDimitry Andric ConsumeToken(); 802*0fca6ea1SDimitry Andric return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 803*0fca6ea1SDimitry Andric OpenACCClauseKind::Gang, GangLoc) 804*0fca6ea1SDimitry Andric .first.isInvalid(); 805*0fca6ea1SDimitry Andric } 806*0fca6ea1SDimitry Andric 807*0fca6ea1SDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) && 808*0fca6ea1SDimitry Andric NextToken().is(tok::colon)) { 809*0fca6ea1SDimitry Andric ConsumeToken(); 810*0fca6ea1SDimitry Andric ConsumeToken(); 811*0fca6ea1SDimitry Andric // Fallthrough to the 'int-expr' handling for when 'num' is omitted. 812*0fca6ea1SDimitry Andric } 813*0fca6ea1SDimitry Andric // This is just the 'num' case where 'num' is optional. 814*0fca6ea1SDimitry Andric return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 815*0fca6ea1SDimitry Andric OpenACCClauseKind::Gang, GangLoc) 816*0fca6ea1SDimitry Andric .first.isInvalid(); 817*0fca6ea1SDimitry Andric } 818*0fca6ea1SDimitry Andric 819*0fca6ea1SDimitry Andric bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) { 820*0fca6ea1SDimitry Andric if (ParseOpenACCGangArg(GangLoc)) { 821*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 822*0fca6ea1SDimitry Andric Parser::StopBeforeMatch); 823*0fca6ea1SDimitry Andric return false; 824*0fca6ea1SDimitry Andric } 825*0fca6ea1SDimitry Andric 826*0fca6ea1SDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 827*0fca6ea1SDimitry Andric ExpectAndConsume(tok::comma); 828*0fca6ea1SDimitry Andric 829*0fca6ea1SDimitry Andric if (ParseOpenACCGangArg(GangLoc)) { 830*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, 831*0fca6ea1SDimitry Andric Parser::StopBeforeMatch); 832*0fca6ea1SDimitry Andric return false; 833*0fca6ea1SDimitry Andric } 8347a6dacacSDimitry Andric } 8357a6dacacSDimitry Andric return false; 8367a6dacacSDimitry Andric } 8377a6dacacSDimitry Andric 8387a6dacacSDimitry Andric // The OpenACC Clause List is a comma or space-delimited list of clauses (see 8397a6dacacSDimitry Andric // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't 8407a6dacacSDimitry Andric // really have its owner grammar and each individual one has its own definition. 8417a6dacacSDimitry Andric // However, they all are named with a single-identifier (or auto/default!) 8427a6dacacSDimitry Andric // token, followed in some cases by either braces or parens. 843*0fca6ea1SDimitry Andric Parser::OpenACCClauseParseResult 844*0fca6ea1SDimitry Andric Parser::ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses, 845*0fca6ea1SDimitry Andric OpenACCDirectiveKind DirKind) { 8467a6dacacSDimitry Andric // A number of clause names are actually keywords, so accept a keyword that 8477a6dacacSDimitry Andric // can be converted to a name. 8487a6dacacSDimitry Andric if (expectIdentifierOrKeyword(*this)) 849*0fca6ea1SDimitry Andric return OpenACCCannotContinue(); 8507a6dacacSDimitry Andric 8517a6dacacSDimitry Andric OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken()); 8527a6dacacSDimitry Andric 853*0fca6ea1SDimitry Andric if (Kind == OpenACCClauseKind::Invalid) { 854*0fca6ea1SDimitry Andric Diag(getCurToken(), diag::err_acc_invalid_clause) 8557a6dacacSDimitry Andric << getCurToken().getIdentifierInfo(); 856*0fca6ea1SDimitry Andric return OpenACCCannotContinue(); 8577a6dacacSDimitry Andric } 8587a6dacacSDimitry Andric 859*0fca6ea1SDimitry Andric // Consume the clause name. 860*0fca6ea1SDimitry Andric SourceLocation ClauseLoc = ConsumeToken(); 861*0fca6ea1SDimitry Andric 862*0fca6ea1SDimitry Andric return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc); 863*0fca6ea1SDimitry Andric } 864*0fca6ea1SDimitry Andric 865*0fca6ea1SDimitry Andric Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams( 866*0fca6ea1SDimitry Andric ArrayRef<const OpenACCClause *> ExistingClauses, 867*0fca6ea1SDimitry Andric OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind, 868*0fca6ea1SDimitry Andric SourceLocation ClauseLoc) { 8697a6dacacSDimitry Andric BalancedDelimiterTracker Parens(*this, tok::l_paren, 8707a6dacacSDimitry Andric tok::annot_pragma_openacc_end); 871*0fca6ea1SDimitry Andric SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc); 8727a6dacacSDimitry Andric 873*0fca6ea1SDimitry Andric if (ClauseHasRequiredParens(DirKind, ClauseKind)) { 8747a6dacacSDimitry Andric if (Parens.expectAndConsume()) { 8757a6dacacSDimitry Andric // We are missing a paren, so assume that the person just forgot the 8767a6dacacSDimitry Andric // parameter. Return 'false' so we try to continue on and parse the next 8777a6dacacSDimitry Andric // clause. 8787a6dacacSDimitry Andric SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end, 8797a6dacacSDimitry Andric Parser::StopBeforeMatch); 880*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 8817a6dacacSDimitry Andric } 882*0fca6ea1SDimitry Andric ParsedClause.setLParenLoc(Parens.getOpenLocation()); 8837a6dacacSDimitry Andric 884*0fca6ea1SDimitry Andric switch (ClauseKind) { 8857a6dacacSDimitry Andric case OpenACCClauseKind::Default: { 8867a6dacacSDimitry Andric Token DefKindTok = getCurToken(); 8877a6dacacSDimitry Andric 888*0fca6ea1SDimitry Andric if (expectIdentifierOrKeyword(*this)) { 889*0fca6ea1SDimitry Andric Parens.skipToEnd(); 890*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 891*0fca6ea1SDimitry Andric } 8927a6dacacSDimitry Andric 8937a6dacacSDimitry Andric ConsumeToken(); 8947a6dacacSDimitry Andric 895*0fca6ea1SDimitry Andric OpenACCDefaultClauseKind DefKind = 896*0fca6ea1SDimitry Andric getOpenACCDefaultClauseKind(DefKindTok); 8977a6dacacSDimitry Andric 898*0fca6ea1SDimitry Andric if (DefKind == OpenACCDefaultClauseKind::Invalid) { 899*0fca6ea1SDimitry Andric Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind); 900*0fca6ea1SDimitry Andric Parens.skipToEnd(); 901*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 902*0fca6ea1SDimitry Andric } 903*0fca6ea1SDimitry Andric 904*0fca6ea1SDimitry Andric ParsedClause.setDefaultDetails(DefKind); 9057a6dacacSDimitry Andric break; 9067a6dacacSDimitry Andric } 9077a6dacacSDimitry Andric case OpenACCClauseKind::If: { 908*0fca6ea1SDimitry Andric ExprResult CondExpr = ParseOpenACCConditionExpr(); 909*0fca6ea1SDimitry Andric ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() 910*0fca6ea1SDimitry Andric : nullptr); 911*0fca6ea1SDimitry Andric 912*0fca6ea1SDimitry Andric if (CondExpr.isInvalid()) { 913*0fca6ea1SDimitry Andric Parens.skipToEnd(); 914*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 915*0fca6ea1SDimitry Andric } 916*0fca6ea1SDimitry Andric 9177a6dacacSDimitry Andric break; 9187a6dacacSDimitry Andric } 9197a6dacacSDimitry Andric case OpenACCClauseKind::CopyIn: 920*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCopyIn: 921*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCopyIn: { 922*0fca6ea1SDimitry Andric bool IsReadOnly = tryParseAndConsumeSpecialTokenKind( 923*0fca6ea1SDimitry Andric *this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind); 924*0fca6ea1SDimitry Andric ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 925*0fca6ea1SDimitry Andric IsReadOnly, 926*0fca6ea1SDimitry Andric /*IsZero=*/false); 9277a6dacacSDimitry Andric break; 928*0fca6ea1SDimitry Andric } 9297a6dacacSDimitry Andric case OpenACCClauseKind::Create: 930*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCreate: 931*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCreate: 9327a6dacacSDimitry Andric case OpenACCClauseKind::CopyOut: 933*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCopyOut: 934*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCopyOut: { 935*0fca6ea1SDimitry Andric bool IsZero = tryParseAndConsumeSpecialTokenKind( 936*0fca6ea1SDimitry Andric *this, OpenACCSpecialTokenKind::Zero, ClauseKind); 937*0fca6ea1SDimitry Andric ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 938*0fca6ea1SDimitry Andric /*IsReadOnly=*/false, IsZero); 9397a6dacacSDimitry Andric break; 940*0fca6ea1SDimitry Andric } 941*0fca6ea1SDimitry Andric case OpenACCClauseKind::Reduction: { 9427a6dacacSDimitry Andric // If we're missing a clause-kind (or it is invalid), see if we can parse 9437a6dacacSDimitry Andric // the var-list anyway. 944*0fca6ea1SDimitry Andric OpenACCReductionOperator Op = ParseReductionOperator(*this); 945*0fca6ea1SDimitry Andric ParsedClause.setReductionDetails(Op, ParseOpenACCVarList(ClauseKind)); 9467a6dacacSDimitry Andric break; 947*0fca6ea1SDimitry Andric } 9487a6dacacSDimitry Andric case OpenACCClauseKind::Self: 9497a6dacacSDimitry Andric // The 'self' clause is a var-list instead of a 'condition' in the case of 9507a6dacacSDimitry Andric // the 'update' clause, so we have to handle it here. U se an assert to 9517a6dacacSDimitry Andric // make sure we get the right differentiator. 9527a6dacacSDimitry Andric assert(DirKind == OpenACCDirectiveKind::Update); 953*0fca6ea1SDimitry Andric [[fallthrough]]; 9547a6dacacSDimitry Andric case OpenACCClauseKind::Delete: 9557a6dacacSDimitry Andric case OpenACCClauseKind::Detach: 9567a6dacacSDimitry Andric case OpenACCClauseKind::Device: 9577a6dacacSDimitry Andric case OpenACCClauseKind::DeviceResident: 9587a6dacacSDimitry Andric case OpenACCClauseKind::Host: 9597a6dacacSDimitry Andric case OpenACCClauseKind::Link: 960*0fca6ea1SDimitry Andric case OpenACCClauseKind::UseDevice: 961*0fca6ea1SDimitry Andric ParseOpenACCVarList(ClauseKind); 962*0fca6ea1SDimitry Andric break; 963*0fca6ea1SDimitry Andric case OpenACCClauseKind::Attach: 964*0fca6ea1SDimitry Andric case OpenACCClauseKind::DevicePtr: 965*0fca6ea1SDimitry Andric ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 966*0fca6ea1SDimitry Andric /*IsReadOnly=*/false, /*IsZero=*/false); 967*0fca6ea1SDimitry Andric break; 968*0fca6ea1SDimitry Andric case OpenACCClauseKind::Copy: 969*0fca6ea1SDimitry Andric case OpenACCClauseKind::PCopy: 970*0fca6ea1SDimitry Andric case OpenACCClauseKind::PresentOrCopy: 971*0fca6ea1SDimitry Andric case OpenACCClauseKind::FirstPrivate: 9727a6dacacSDimitry Andric case OpenACCClauseKind::NoCreate: 9737a6dacacSDimitry Andric case OpenACCClauseKind::Present: 9747a6dacacSDimitry Andric case OpenACCClauseKind::Private: 975*0fca6ea1SDimitry Andric ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind), 976*0fca6ea1SDimitry Andric /*IsReadOnly=*/false, /*IsZero=*/false); 9777a6dacacSDimitry Andric break; 9787a6dacacSDimitry Andric case OpenACCClauseKind::Collapse: { 9797a6dacacSDimitry Andric tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Force, 980*0fca6ea1SDimitry Andric ClauseKind); 9817a6dacacSDimitry Andric ExprResult NumLoops = 9827a6dacacSDimitry Andric getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); 983*0fca6ea1SDimitry Andric if (NumLoops.isInvalid()) { 984*0fca6ea1SDimitry Andric Parens.skipToEnd(); 985*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 986*0fca6ea1SDimitry Andric } 9877a6dacacSDimitry Andric break; 9887a6dacacSDimitry Andric } 9897a6dacacSDimitry Andric case OpenACCClauseKind::Bind: { 9907a6dacacSDimitry Andric ExprResult BindArg = ParseOpenACCBindClauseArgument(); 991*0fca6ea1SDimitry Andric if (BindArg.isInvalid()) { 992*0fca6ea1SDimitry Andric Parens.skipToEnd(); 993*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 994*0fca6ea1SDimitry Andric } 9957a6dacacSDimitry Andric break; 9967a6dacacSDimitry Andric } 997*0fca6ea1SDimitry Andric case OpenACCClauseKind::NumGangs: { 998*0fca6ea1SDimitry Andric llvm::SmallVector<Expr *> IntExprs; 999*0fca6ea1SDimitry Andric 1000*0fca6ea1SDimitry Andric if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid, 1001*0fca6ea1SDimitry Andric OpenACCClauseKind::NumGangs, ClauseLoc, 1002*0fca6ea1SDimitry Andric IntExprs)) { 1003*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1004*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1005*0fca6ea1SDimitry Andric } 1006*0fca6ea1SDimitry Andric ParsedClause.setIntExprDetails(std::move(IntExprs)); 1007*0fca6ea1SDimitry Andric break; 1008*0fca6ea1SDimitry Andric } 10097a6dacacSDimitry Andric case OpenACCClauseKind::NumWorkers: 10107a6dacacSDimitry Andric case OpenACCClauseKind::DeviceNum: 10117a6dacacSDimitry Andric case OpenACCClauseKind::DefaultAsync: 10127a6dacacSDimitry Andric case OpenACCClauseKind::VectorLength: { 1013*0fca6ea1SDimitry Andric ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 1014*0fca6ea1SDimitry Andric ClauseKind, ClauseLoc) 1015*0fca6ea1SDimitry Andric .first; 1016*0fca6ea1SDimitry Andric if (IntExpr.isInvalid()) { 1017*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1018*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1019*0fca6ea1SDimitry Andric } 1020*0fca6ea1SDimitry Andric 1021*0fca6ea1SDimitry Andric // TODO OpenACC: as we implement the 'rest' of the above, this 'if' should 1022*0fca6ea1SDimitry Andric // be removed leaving just the 'setIntExprDetails'. 1023*0fca6ea1SDimitry Andric if (ClauseKind == OpenACCClauseKind::NumWorkers || 1024*0fca6ea1SDimitry Andric ClauseKind == OpenACCClauseKind::VectorLength) 1025*0fca6ea1SDimitry Andric ParsedClause.setIntExprDetails(IntExpr.get()); 1026*0fca6ea1SDimitry Andric 10277a6dacacSDimitry Andric break; 10287a6dacacSDimitry Andric } 10297a6dacacSDimitry Andric case OpenACCClauseKind::DType: 1030*0fca6ea1SDimitry Andric case OpenACCClauseKind::DeviceType: { 1031*0fca6ea1SDimitry Andric llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> Archs; 10327a6dacacSDimitry Andric if (getCurToken().is(tok::star)) { 10337a6dacacSDimitry Andric // FIXME: We want to mark that this is an 'everything else' type of 10347a6dacacSDimitry Andric // device_type in Sema. 1035*0fca6ea1SDimitry Andric ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}}); 1036*0fca6ea1SDimitry Andric } else if (!ParseOpenACCDeviceTypeList(Archs)) { 1037*0fca6ea1SDimitry Andric ParsedClause.setDeviceTypeDetails(std::move(Archs)); 1038*0fca6ea1SDimitry Andric } else { 1039*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1040*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1041*0fca6ea1SDimitry Andric } 1042*0fca6ea1SDimitry Andric break; 1043*0fca6ea1SDimitry Andric } 1044*0fca6ea1SDimitry Andric case OpenACCClauseKind::Tile: 1045*0fca6ea1SDimitry Andric if (ParseOpenACCSizeExprList()) { 1046*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1047*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 10487a6dacacSDimitry Andric } 10497a6dacacSDimitry Andric break; 10507a6dacacSDimitry Andric default: 10517a6dacacSDimitry Andric llvm_unreachable("Not a required parens type?"); 10527a6dacacSDimitry Andric } 10537a6dacacSDimitry Andric 1054*0fca6ea1SDimitry Andric ParsedClause.setEndLoc(getCurToken().getLocation()); 1055*0fca6ea1SDimitry Andric 1056*0fca6ea1SDimitry Andric if (Parens.consumeClose()) 1057*0fca6ea1SDimitry Andric return OpenACCCannotContinue(); 1058*0fca6ea1SDimitry Andric 1059*0fca6ea1SDimitry Andric } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) { 10607a6dacacSDimitry Andric if (!Parens.consumeOpen()) { 1061*0fca6ea1SDimitry Andric ParsedClause.setLParenLoc(Parens.getOpenLocation()); 1062*0fca6ea1SDimitry Andric switch (ClauseKind) { 10637a6dacacSDimitry Andric case OpenACCClauseKind::Self: { 10647a6dacacSDimitry Andric assert(DirKind != OpenACCDirectiveKind::Update); 1065*0fca6ea1SDimitry Andric ExprResult CondExpr = ParseOpenACCConditionExpr(); 1066*0fca6ea1SDimitry Andric ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get() 1067*0fca6ea1SDimitry Andric : nullptr); 1068*0fca6ea1SDimitry Andric 1069*0fca6ea1SDimitry Andric if (CondExpr.isInvalid()) { 1070*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1071*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1072*0fca6ea1SDimitry Andric } 10737a6dacacSDimitry Andric break; 10747a6dacacSDimitry Andric } 10757a6dacacSDimitry Andric case OpenACCClauseKind::Vector: 10767a6dacacSDimitry Andric case OpenACCClauseKind::Worker: { 10777a6dacacSDimitry Andric tryParseAndConsumeSpecialTokenKind(*this, 1078*0fca6ea1SDimitry Andric ClauseKind == 1079*0fca6ea1SDimitry Andric OpenACCClauseKind::Vector 10807a6dacacSDimitry Andric ? OpenACCSpecialTokenKind::Length 10817a6dacacSDimitry Andric : OpenACCSpecialTokenKind::Num, 1082*0fca6ea1SDimitry Andric ClauseKind); 1083*0fca6ea1SDimitry Andric ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid, 1084*0fca6ea1SDimitry Andric ClauseKind, ClauseLoc) 1085*0fca6ea1SDimitry Andric .first; 1086*0fca6ea1SDimitry Andric if (IntExpr.isInvalid()) { 1087*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1088*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1089*0fca6ea1SDimitry Andric } 1090*0fca6ea1SDimitry Andric break; 1091*0fca6ea1SDimitry Andric } 1092*0fca6ea1SDimitry Andric case OpenACCClauseKind::Async: { 1093*0fca6ea1SDimitry Andric ExprResult AsyncArg = 1094*0fca6ea1SDimitry Andric ParseOpenACCAsyncArgument(OpenACCDirectiveKind::Invalid, 1095*0fca6ea1SDimitry Andric OpenACCClauseKind::Async, ClauseLoc) 1096*0fca6ea1SDimitry Andric .first; 1097*0fca6ea1SDimitry Andric ParsedClause.setIntExprDetails(AsyncArg.isUsable() ? AsyncArg.get() 1098*0fca6ea1SDimitry Andric : nullptr); 1099*0fca6ea1SDimitry Andric if (AsyncArg.isInvalid()) { 1100*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1101*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1102*0fca6ea1SDimitry Andric } 1103*0fca6ea1SDimitry Andric break; 1104*0fca6ea1SDimitry Andric } 1105*0fca6ea1SDimitry Andric case OpenACCClauseKind::Gang: 1106*0fca6ea1SDimitry Andric if (ParseOpenACCGangArgList(ClauseLoc)) { 1107*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1108*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1109*0fca6ea1SDimitry Andric } 1110*0fca6ea1SDimitry Andric break; 1111*0fca6ea1SDimitry Andric case OpenACCClauseKind::Wait: { 1112*0fca6ea1SDimitry Andric OpenACCWaitParseInfo Info = 1113*0fca6ea1SDimitry Andric ParseOpenACCWaitArgument(ClauseLoc, 1114*0fca6ea1SDimitry Andric /*IsDirective=*/false); 1115*0fca6ea1SDimitry Andric if (Info.Failed) { 1116*0fca6ea1SDimitry Andric Parens.skipToEnd(); 1117*0fca6ea1SDimitry Andric return OpenACCCanContinue(); 1118*0fca6ea1SDimitry Andric } 1119*0fca6ea1SDimitry Andric 1120*0fca6ea1SDimitry Andric ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc, 1121*0fca6ea1SDimitry Andric std::move(Info.QueueIdExprs)); 11227a6dacacSDimitry Andric break; 11237a6dacacSDimitry Andric } 11247a6dacacSDimitry Andric default: 11257a6dacacSDimitry Andric llvm_unreachable("Not an optional parens type?"); 11267a6dacacSDimitry Andric } 1127*0fca6ea1SDimitry Andric ParsedClause.setEndLoc(getCurToken().getLocation()); 1128*0fca6ea1SDimitry Andric if (Parens.consumeClose()) 1129*0fca6ea1SDimitry Andric return OpenACCCannotContinue(); 1130*0fca6ea1SDimitry Andric } else { 1131*0fca6ea1SDimitry Andric // If we have optional parens, make sure we set the end-location to the 1132*0fca6ea1SDimitry Andric // clause, as we are a 'single token' clause. 1133*0fca6ea1SDimitry Andric ParsedClause.setEndLoc(ClauseLoc); 11347a6dacacSDimitry Andric } 1135*0fca6ea1SDimitry Andric } else { 1136*0fca6ea1SDimitry Andric ParsedClause.setEndLoc(ClauseLoc); 11377a6dacacSDimitry Andric } 1138*0fca6ea1SDimitry Andric return OpenACCSuccess( 1139*0fca6ea1SDimitry Andric Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause)); 1140*0fca6ea1SDimitry Andric } 1141*0fca6ea1SDimitry Andric 1142*0fca6ea1SDimitry Andric /// OpenACC 3.3 section 2.16: 1143*0fca6ea1SDimitry Andric /// In this section and throughout the specification, the term async-argument 1144*0fca6ea1SDimitry Andric /// means a nonnegative scalar integer expression (int for C or C++, integer for 1145*0fca6ea1SDimitry Andric /// Fortran), or one of the special values acc_async_noval or acc_async_sync, as 1146*0fca6ea1SDimitry Andric /// defined in the C header file and the Fortran openacc module. The special 1147*0fca6ea1SDimitry Andric /// values are negative values, so as not to conflict with a user-specified 1148*0fca6ea1SDimitry Andric /// nonnegative async-argument. 1149*0fca6ea1SDimitry Andric Parser::OpenACCIntExprParseResult 1150*0fca6ea1SDimitry Andric Parser::ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, OpenACCClauseKind CK, 1151*0fca6ea1SDimitry Andric SourceLocation Loc) { 1152*0fca6ea1SDimitry Andric return ParseOpenACCIntExpr(DK, CK, Loc); 11537a6dacacSDimitry Andric } 11545f757f3fSDimitry Andric 11555f757f3fSDimitry Andric /// OpenACC 3.3, section 2.16: 11565f757f3fSDimitry Andric /// In this section and throughout the specification, the term wait-argument 11575f757f3fSDimitry Andric /// means: 11585f757f3fSDimitry Andric /// [ devnum : int-expr : ] [ queues : ] async-argument-list 1159*0fca6ea1SDimitry Andric Parser::OpenACCWaitParseInfo 1160*0fca6ea1SDimitry Andric Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) { 1161*0fca6ea1SDimitry Andric OpenACCWaitParseInfo Result; 11625f757f3fSDimitry Andric // [devnum : int-expr : ] 11635f757f3fSDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && 11645f757f3fSDimitry Andric NextToken().is(tok::colon)) { 11655f757f3fSDimitry Andric // Consume devnum. 11665f757f3fSDimitry Andric ConsumeToken(); 11675f757f3fSDimitry Andric // Consume colon. 11685f757f3fSDimitry Andric ConsumeToken(); 11695f757f3fSDimitry Andric 1170*0fca6ea1SDimitry Andric OpenACCIntExprParseResult Res = ParseOpenACCIntExpr( 1171*0fca6ea1SDimitry Andric IsDirective ? OpenACCDirectiveKind::Wait 1172*0fca6ea1SDimitry Andric : OpenACCDirectiveKind::Invalid, 1173*0fca6ea1SDimitry Andric IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, 1174*0fca6ea1SDimitry Andric Loc); 1175*0fca6ea1SDimitry Andric if (Res.first.isInvalid() && 1176*0fca6ea1SDimitry Andric Res.second == OpenACCParseCanContinue::Cannot) { 1177*0fca6ea1SDimitry Andric Result.Failed = true; 1178*0fca6ea1SDimitry Andric return Result; 1179*0fca6ea1SDimitry Andric } 11805f757f3fSDimitry Andric 1181*0fca6ea1SDimitry Andric if (ExpectAndConsume(tok::colon)) { 1182*0fca6ea1SDimitry Andric Result.Failed = true; 1183*0fca6ea1SDimitry Andric return Result; 1184*0fca6ea1SDimitry Andric } 1185*0fca6ea1SDimitry Andric 1186*0fca6ea1SDimitry Andric Result.DevNumExpr = Res.first.get(); 11875f757f3fSDimitry Andric } 11885f757f3fSDimitry Andric 11895f757f3fSDimitry Andric // [ queues : ] 11905f757f3fSDimitry Andric if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && 11915f757f3fSDimitry Andric NextToken().is(tok::colon)) { 11925f757f3fSDimitry Andric // Consume queues. 1193*0fca6ea1SDimitry Andric Result.QueuesLoc = ConsumeToken(); 11945f757f3fSDimitry Andric // Consume colon. 11955f757f3fSDimitry Andric ConsumeToken(); 11965f757f3fSDimitry Andric } 11975f757f3fSDimitry Andric 11985f757f3fSDimitry Andric // OpenACC 3.3, section 2.16: 11995f757f3fSDimitry Andric // the term 'async-argument' means a nonnegative scalar integer expression, or 12005f757f3fSDimitry Andric // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined 12015f757f3fSDimitry Andric // in the C header file and the Fortran opacc module. 12025f757f3fSDimitry Andric bool FirstArg = true; 12035f757f3fSDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 12045f757f3fSDimitry Andric if (!FirstArg) { 1205*0fca6ea1SDimitry Andric if (ExpectAndConsume(tok::comma)) { 1206*0fca6ea1SDimitry Andric Result.Failed = true; 1207*0fca6ea1SDimitry Andric return Result; 1208*0fca6ea1SDimitry Andric } 12095f757f3fSDimitry Andric } 12105f757f3fSDimitry Andric FirstArg = false; 12115f757f3fSDimitry Andric 1212*0fca6ea1SDimitry Andric OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument( 1213*0fca6ea1SDimitry Andric IsDirective ? OpenACCDirectiveKind::Wait 1214*0fca6ea1SDimitry Andric : OpenACCDirectiveKind::Invalid, 1215*0fca6ea1SDimitry Andric IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait, 1216*0fca6ea1SDimitry Andric Loc); 12175f757f3fSDimitry Andric 1218*0fca6ea1SDimitry Andric if (Res.first.isInvalid() && 1219*0fca6ea1SDimitry Andric Res.second == OpenACCParseCanContinue::Cannot) { 1220*0fca6ea1SDimitry Andric Result.Failed = true; 1221*0fca6ea1SDimitry Andric return Result; 12225f757f3fSDimitry Andric } 12235f757f3fSDimitry Andric 1224*0fca6ea1SDimitry Andric Result.QueueIdExprs.push_back(Res.first.get()); 1225*0fca6ea1SDimitry Andric } 1226*0fca6ea1SDimitry Andric 1227*0fca6ea1SDimitry Andric return Result; 12285f757f3fSDimitry Andric } 12295f757f3fSDimitry Andric 12305f757f3fSDimitry Andric ExprResult Parser::ParseOpenACCIDExpression() { 12315f757f3fSDimitry Andric ExprResult Res; 12325f757f3fSDimitry Andric if (getLangOpts().CPlusPlus) { 12337a6dacacSDimitry Andric Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true); 12345f757f3fSDimitry Andric } else { 12355f757f3fSDimitry Andric // There isn't anything quite the same as ParseCXXIdExpression for C, so we 12365f757f3fSDimitry Andric // need to get the identifier, then call into Sema ourselves. 12375f757f3fSDimitry Andric 12385f757f3fSDimitry Andric if (Tok.isNot(tok::identifier)) { 12395f757f3fSDimitry Andric Diag(Tok, diag::err_expected) << tok::identifier; 12405f757f3fSDimitry Andric return ExprError(); 12415f757f3fSDimitry Andric } 12425f757f3fSDimitry Andric 12435f757f3fSDimitry Andric Token FuncName = getCurToken(); 12445f757f3fSDimitry Andric UnqualifiedId Name; 12455f757f3fSDimitry Andric CXXScopeSpec ScopeSpec; 12465f757f3fSDimitry Andric SourceLocation TemplateKWLoc; 12475f757f3fSDimitry Andric Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken()); 12485f757f3fSDimitry Andric 12495f757f3fSDimitry Andric // Ensure this is a valid identifier. We don't accept causing implicit 12505f757f3fSDimitry Andric // function declarations per the spec, so always claim to not have trailing 12515f757f3fSDimitry Andric // L Paren. 12525f757f3fSDimitry Andric Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc, 12535f757f3fSDimitry Andric Name, /*HasTrailingLParen=*/false, 12545f757f3fSDimitry Andric /*isAddressOfOperand=*/false); 12555f757f3fSDimitry Andric } 12565f757f3fSDimitry Andric 12575f757f3fSDimitry Andric return getActions().CorrectDelayedTyposInExpr(Res); 12585f757f3fSDimitry Andric } 12595f757f3fSDimitry Andric 12607a6dacacSDimitry Andric ExprResult Parser::ParseOpenACCBindClauseArgument() { 12617a6dacacSDimitry Andric // OpenACC 3.3 section 2.15: 12627a6dacacSDimitry Andric // The bind clause specifies the name to use when calling the procedure on a 12637a6dacacSDimitry Andric // device other than the host. If the name is specified as an identifier, it 12647a6dacacSDimitry Andric // is called as if that name were specified in the language being compiled. If 12657a6dacacSDimitry Andric // the name is specified as a string, the string is used for the procedure 12667a6dacacSDimitry Andric // name unmodified. 12677a6dacacSDimitry Andric if (getCurToken().is(tok::r_paren)) { 12687a6dacacSDimitry Andric Diag(getCurToken(), diag::err_acc_incorrect_bind_arg); 12697a6dacacSDimitry Andric return ExprError(); 12707a6dacacSDimitry Andric } 12717a6dacacSDimitry Andric 12727a6dacacSDimitry Andric if (tok::isStringLiteral(getCurToken().getKind())) 12737a6dacacSDimitry Andric return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression( 12747a6dacacSDimitry Andric /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true)); 12757a6dacacSDimitry Andric 12767a6dacacSDimitry Andric return ParseOpenACCIDExpression(); 12777a6dacacSDimitry Andric } 12787a6dacacSDimitry Andric 1279297eecfbSDimitry Andric /// OpenACC 3.3, section 1.6: 1280297eecfbSDimitry Andric /// In this spec, a 'var' (in italics) is one of the following: 1281*0fca6ea1SDimitry Andric /// - a variable name (a scalar, array, or composite variable name) 1282297eecfbSDimitry Andric /// - a subarray specification with subscript ranges 1283297eecfbSDimitry Andric /// - an array element 1284297eecfbSDimitry Andric /// - a member of a composite variable 1285297eecfbSDimitry Andric /// - a common block name between slashes (fortran only) 1286*0fca6ea1SDimitry Andric Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCClauseKind CK) { 1287297eecfbSDimitry Andric OpenACCArraySectionRAII ArraySections(*this); 1288*0fca6ea1SDimitry Andric 1289*0fca6ea1SDimitry Andric ExprResult Res = ParseAssignmentExpression(); 1290*0fca6ea1SDimitry Andric if (!Res.isUsable()) 1291*0fca6ea1SDimitry Andric return {Res, OpenACCParseCanContinue::Cannot}; 1292*0fca6ea1SDimitry Andric 1293*0fca6ea1SDimitry Andric Res = getActions().CorrectDelayedTyposInExpr(Res.get()); 1294*0fca6ea1SDimitry Andric if (!Res.isUsable()) 1295*0fca6ea1SDimitry Andric return {Res, OpenACCParseCanContinue::Can}; 1296*0fca6ea1SDimitry Andric 1297*0fca6ea1SDimitry Andric Res = getActions().OpenACC().ActOnVar(CK, Res.get()); 1298*0fca6ea1SDimitry Andric 1299*0fca6ea1SDimitry Andric return {Res, OpenACCParseCanContinue::Can}; 1300*0fca6ea1SDimitry Andric } 1301*0fca6ea1SDimitry Andric 1302*0fca6ea1SDimitry Andric llvm::SmallVector<Expr *> Parser::ParseOpenACCVarList(OpenACCClauseKind CK) { 1303*0fca6ea1SDimitry Andric llvm::SmallVector<Expr *> Vars; 1304*0fca6ea1SDimitry Andric 1305*0fca6ea1SDimitry Andric auto [Res, CanContinue] = ParseOpenACCVar(CK); 1306*0fca6ea1SDimitry Andric if (Res.isUsable()) { 1307*0fca6ea1SDimitry Andric Vars.push_back(Res.get()); 1308*0fca6ea1SDimitry Andric } else if (CanContinue == OpenACCParseCanContinue::Cannot) { 1309*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch); 1310*0fca6ea1SDimitry Andric return Vars; 1311*0fca6ea1SDimitry Andric } 1312*0fca6ea1SDimitry Andric 1313*0fca6ea1SDimitry Andric while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { 1314*0fca6ea1SDimitry Andric ExpectAndConsume(tok::comma); 1315*0fca6ea1SDimitry Andric 1316*0fca6ea1SDimitry Andric auto [Res, CanContinue] = ParseOpenACCVar(CK); 1317*0fca6ea1SDimitry Andric 1318*0fca6ea1SDimitry Andric if (Res.isUsable()) { 1319*0fca6ea1SDimitry Andric Vars.push_back(Res.get()); 1320*0fca6ea1SDimitry Andric } else if (CanContinue == OpenACCParseCanContinue::Cannot) { 1321*0fca6ea1SDimitry Andric SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch); 1322*0fca6ea1SDimitry Andric return Vars; 1323*0fca6ea1SDimitry Andric } 1324*0fca6ea1SDimitry Andric } 1325*0fca6ea1SDimitry Andric return Vars; 13265f757f3fSDimitry Andric } 13275f757f3fSDimitry Andric 13285f757f3fSDimitry Andric /// OpenACC 3.3, section 2.10: 13295f757f3fSDimitry Andric /// In C and C++, the syntax of the cache directive is: 13305f757f3fSDimitry Andric /// 13315f757f3fSDimitry Andric /// #pragma acc cache ([readonly:]var-list) new-line 13325f757f3fSDimitry Andric void Parser::ParseOpenACCCacheVarList() { 13335f757f3fSDimitry Andric // If this is the end of the line, just return 'false' and count on the close 13345f757f3fSDimitry Andric // paren diagnostic to catch the issue. 13355f757f3fSDimitry Andric if (getCurToken().isAnnotation()) 13365f757f3fSDimitry Andric return; 13375f757f3fSDimitry Andric 13385f757f3fSDimitry Andric // The VarList is an optional `readonly:` followed by a list of a variable 13397a6dacacSDimitry Andric // specifications. Consume something that looks like a 'tag', and diagnose if 13407a6dacacSDimitry Andric // it isn't 'readonly'. 13417a6dacacSDimitry Andric if (tryParseAndConsumeSpecialTokenKind(*this, 13427a6dacacSDimitry Andric OpenACCSpecialTokenKind::ReadOnly, 13437a6dacacSDimitry Andric OpenACCDirectiveKind::Cache)) { 13445f757f3fSDimitry Andric // FIXME: Record that this is a 'readonly' so that we can use that during 13455f757f3fSDimitry Andric // Sema/AST generation. 13465f757f3fSDimitry Andric } 13475f757f3fSDimitry Andric 1348*0fca6ea1SDimitry Andric // ParseOpenACCVarList should leave us before a r-paren, so no need to skip 1349*0fca6ea1SDimitry Andric // anything here. 1350*0fca6ea1SDimitry Andric ParseOpenACCVarList(OpenACCClauseKind::Invalid); 13515f757f3fSDimitry Andric } 13525f757f3fSDimitry Andric 1353*0fca6ea1SDimitry Andric Parser::OpenACCDirectiveParseInfo 1354*0fca6ea1SDimitry Andric Parser::ParseOpenACCDirective() { 1355*0fca6ea1SDimitry Andric SourceLocation StartLoc = ConsumeAnnotationToken(); 1356*0fca6ea1SDimitry Andric SourceLocation DirLoc = getCurToken().getLocation(); 13575f757f3fSDimitry Andric OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); 13585f757f3fSDimitry Andric 1359*0fca6ea1SDimitry Andric getActions().OpenACC().ActOnConstruct(DirKind, DirLoc); 1360*0fca6ea1SDimitry Andric 13615f757f3fSDimitry Andric // Once we've parsed the construct/directive name, some have additional 13625f757f3fSDimitry Andric // specifiers that need to be taken care of. Atomic has an 'atomic-clause' 13635f757f3fSDimitry Andric // that needs to be parsed. 13645f757f3fSDimitry Andric if (DirKind == OpenACCDirectiveKind::Atomic) 13655f757f3fSDimitry Andric ParseOpenACCAtomicKind(*this); 13665f757f3fSDimitry Andric 13675f757f3fSDimitry Andric // We've successfully parsed the construct/directive name, however a few of 13685f757f3fSDimitry Andric // the constructs have optional parens that contain further details. 13695f757f3fSDimitry Andric BalancedDelimiterTracker T(*this, tok::l_paren, 13705f757f3fSDimitry Andric tok::annot_pragma_openacc_end); 13715f757f3fSDimitry Andric 13725f757f3fSDimitry Andric if (!T.consumeOpen()) { 13735f757f3fSDimitry Andric switch (DirKind) { 13745f757f3fSDimitry Andric default: 13755f757f3fSDimitry Andric Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren); 13765f757f3fSDimitry Andric T.skipToEnd(); 13775f757f3fSDimitry Andric break; 13785f757f3fSDimitry Andric case OpenACCDirectiveKind::Routine: { 13795f757f3fSDimitry Andric // Routine has an optional paren-wrapped name of a function in the local 13805f757f3fSDimitry Andric // scope. We parse the name, emitting any diagnostics 13815f757f3fSDimitry Andric ExprResult RoutineName = ParseOpenACCIDExpression(); 13825f757f3fSDimitry Andric // If the routine name is invalid, just skip until the closing paren to 13835f757f3fSDimitry Andric // recover more gracefully. 13845f757f3fSDimitry Andric if (RoutineName.isInvalid()) 13855f757f3fSDimitry Andric T.skipToEnd(); 13865f757f3fSDimitry Andric else 13875f757f3fSDimitry Andric T.consumeClose(); 13885f757f3fSDimitry Andric break; 13895f757f3fSDimitry Andric } 13905f757f3fSDimitry Andric case OpenACCDirectiveKind::Cache: 13915f757f3fSDimitry Andric ParseOpenACCCacheVarList(); 13925f757f3fSDimitry Andric // The ParseOpenACCCacheVarList function manages to recover from failures, 13935f757f3fSDimitry Andric // so we can always consume the close. 13945f757f3fSDimitry Andric T.consumeClose(); 13955f757f3fSDimitry Andric break; 13965f757f3fSDimitry Andric case OpenACCDirectiveKind::Wait: 13975f757f3fSDimitry Andric // OpenACC has an optional paren-wrapped 'wait-argument'. 1398*0fca6ea1SDimitry Andric if (ParseOpenACCWaitArgument(DirLoc, /*IsDirective=*/true).Failed) 13995f757f3fSDimitry Andric T.skipToEnd(); 14005f757f3fSDimitry Andric else 14015f757f3fSDimitry Andric T.consumeClose(); 14025f757f3fSDimitry Andric break; 14035f757f3fSDimitry Andric } 14045f757f3fSDimitry Andric } else if (DirKind == OpenACCDirectiveKind::Cache) { 14055f757f3fSDimitry Andric // Cache's paren var-list is required, so error here if it isn't provided. 14065f757f3fSDimitry Andric // We know that the consumeOpen above left the first non-paren here, so 14075f757f3fSDimitry Andric // diagnose, then continue as if it was completely omitted. 14085f757f3fSDimitry Andric Diag(Tok, diag::err_expected) << tok::l_paren; 14095f757f3fSDimitry Andric } 14105f757f3fSDimitry Andric 1411*0fca6ea1SDimitry Andric // Parses the list of clauses, if present, plus set up return value. 1412*0fca6ea1SDimitry Andric OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, DirLoc, 1413*0fca6ea1SDimitry Andric SourceLocation{}, 1414*0fca6ea1SDimitry Andric ParseOpenACCClauseList(DirKind)}; 14155f757f3fSDimitry Andric 1416cb14a3feSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc_end) && 1417cb14a3feSDimitry Andric "Didn't parse all OpenACC Clauses"); 1418*0fca6ea1SDimitry Andric ParseInfo.EndLoc = ConsumeAnnotationToken(); 1419*0fca6ea1SDimitry Andric assert(ParseInfo.EndLoc.isValid() && 1420*0fca6ea1SDimitry Andric "Terminating annotation token not present"); 1421*0fca6ea1SDimitry Andric 1422*0fca6ea1SDimitry Andric return ParseInfo; 14235f757f3fSDimitry Andric } 14245f757f3fSDimitry Andric 14255f757f3fSDimitry Andric // Parse OpenACC directive on a declaration. 14265f757f3fSDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { 14275f757f3fSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 14285f757f3fSDimitry Andric 14295f757f3fSDimitry Andric ParsingOpenACCDirectiveRAII DirScope(*this); 14305f757f3fSDimitry Andric 1431*0fca6ea1SDimitry Andric OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); 14325f757f3fSDimitry Andric 1433*0fca6ea1SDimitry Andric if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind, 1434*0fca6ea1SDimitry Andric DirInfo.StartLoc)) 14355f757f3fSDimitry Andric return nullptr; 1436*0fca6ea1SDimitry Andric 1437*0fca6ea1SDimitry Andric // TODO OpenACC: Do whatever decl parsing is required here. 1438*0fca6ea1SDimitry Andric return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective()); 14395f757f3fSDimitry Andric } 14405f757f3fSDimitry Andric 14415f757f3fSDimitry Andric // Parse OpenACC Directive on a Statement. 14425f757f3fSDimitry Andric StmtResult Parser::ParseOpenACCDirectiveStmt() { 14435f757f3fSDimitry Andric assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); 14445f757f3fSDimitry Andric 14455f757f3fSDimitry Andric ParsingOpenACCDirectiveRAII DirScope(*this); 14465f757f3fSDimitry Andric 1447*0fca6ea1SDimitry Andric OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); 1448*0fca6ea1SDimitry Andric if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind, 1449*0fca6ea1SDimitry Andric DirInfo.StartLoc)) 1450*0fca6ea1SDimitry Andric return StmtError(); 14515f757f3fSDimitry Andric 1452*0fca6ea1SDimitry Andric StmtResult AssocStmt; 1453*0fca6ea1SDimitry Andric SemaOpenACC::AssociatedStmtRAII AssocStmtRAII(getActions().OpenACC(), 1454*0fca6ea1SDimitry Andric DirInfo.DirKind); 1455*0fca6ea1SDimitry Andric if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) { 1456*0fca6ea1SDimitry Andric ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false); 1457*0fca6ea1SDimitry Andric ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind)); 1458*0fca6ea1SDimitry Andric 1459*0fca6ea1SDimitry Andric AssocStmt = getActions().OpenACC().ActOnAssociatedStmt( 1460*0fca6ea1SDimitry Andric DirInfo.StartLoc, DirInfo.DirKind, ParseStatement()); 1461*0fca6ea1SDimitry Andric } 1462*0fca6ea1SDimitry Andric 1463*0fca6ea1SDimitry Andric return getActions().OpenACC().ActOnEndStmtDirective( 1464*0fca6ea1SDimitry Andric DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.EndLoc, 1465*0fca6ea1SDimitry Andric DirInfo.Clauses, AssocStmt); 14665f757f3fSDimitry Andric } 1467