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