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