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