xref: /freebsd/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===--- ParseOpenACC.cpp - OpenACC-specific parsing support --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the parsing logic for OpenACC language features.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/OpenACCClause.h"
14 #include "clang/Basic/DiagnosticParse.h"
15 #include "clang/Basic/OpenACCKinds.h"
16 #include "clang/Parse/Parser.h"
17 #include "clang/Parse/RAIIObjectsForParser.h"
18 #include "clang/Sema/ParsedAttr.h"
19 #include "clang/Sema/SemaOpenACC.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/StringSwitch.h"
22 
23 using namespace clang;
24 using namespace llvm;
25 
26 namespace {
27 // An enum that contains the extended 'partial' parsed variants. This type
28 // should never escape the initial parse functionality, but is useful for
29 // simplifying the implementation.
30 enum class OpenACCDirectiveKindEx {
31   Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid),
32   // 'enter data' and 'exit data'
33   Enter,
34   Exit,
35 };
36 
37 // Translate single-token string representations to the OpenACC Directive Kind.
38 // This doesn't completely comprehend 'Compound Constructs' (as it just
39 // identifies the first token), and doesn't fully handle 'enter data', 'exit
40 // data', nor any of the 'atomic' variants, just the first token of each.  So
41 // this should only be used by `ParseOpenACCDirectiveKind`.
getOpenACCDirectiveKind(Token Tok)42 OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {
43   if (!Tok.is(tok::identifier))
44     return OpenACCDirectiveKindEx::Invalid;
45   OpenACCDirectiveKind DirKind =
46       llvm::StringSwitch<OpenACCDirectiveKind>(
47           Tok.getIdentifierInfo()->getName())
48           .Case("parallel", OpenACCDirectiveKind::Parallel)
49           .Case("serial", OpenACCDirectiveKind::Serial)
50           .Case("kernels", OpenACCDirectiveKind::Kernels)
51           .Case("data", OpenACCDirectiveKind::Data)
52           .Case("host_data", OpenACCDirectiveKind::HostData)
53           .Case("loop", OpenACCDirectiveKind::Loop)
54           .Case("cache", OpenACCDirectiveKind::Cache)
55           .Case("atomic", OpenACCDirectiveKind::Atomic)
56           .Case("routine", OpenACCDirectiveKind::Routine)
57           .Case("declare", OpenACCDirectiveKind::Declare)
58           .Case("init", OpenACCDirectiveKind::Init)
59           .Case("shutdown", OpenACCDirectiveKind::Shutdown)
60           .Case("set", OpenACCDirectiveKind::Set)
61           .Case("update", OpenACCDirectiveKind::Update)
62           .Case("wait", OpenACCDirectiveKind::Wait)
63           .Default(OpenACCDirectiveKind::Invalid);
64 
65   if (DirKind != OpenACCDirectiveKind::Invalid)
66     return static_cast<OpenACCDirectiveKindEx>(DirKind);
67 
68   return llvm::StringSwitch<OpenACCDirectiveKindEx>(
69              Tok.getIdentifierInfo()->getName())
70       .Case("enter", OpenACCDirectiveKindEx::Enter)
71       .Case("exit", OpenACCDirectiveKindEx::Exit)
72       .Default(OpenACCDirectiveKindEx::Invalid);
73 }
74 
75 // Translate single-token string representations to the OpenCC Clause Kind.
getOpenACCClauseKind(Token Tok)76 OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
77   // auto is a keyword in some language modes, so make sure we parse it
78   // correctly.
79   if (Tok.is(tok::kw_auto))
80     return OpenACCClauseKind::Auto;
81 
82   // default is a keyword, so make sure we parse it correctly.
83   if (Tok.is(tok::kw_default))
84     return OpenACCClauseKind::Default;
85 
86   // if is also a keyword, make sure we parse it correctly.
87   if (Tok.is(tok::kw_if))
88     return OpenACCClauseKind::If;
89 
90   // 'private' is also a keyword, make sure we parse it correctly.
91   if (Tok.is(tok::kw_private))
92     return OpenACCClauseKind::Private;
93 
94   // 'delete' is a keyword, make sure we parse it correctly.
95   if (Tok.is(tok::kw_delete))
96     return OpenACCClauseKind::Delete;
97 
98   if (!Tok.is(tok::identifier))
99     return OpenACCClauseKind::Invalid;
100 
101   return llvm::StringSwitch<OpenACCClauseKind>(
102              Tok.getIdentifierInfo()->getName())
103       .Case("async", OpenACCClauseKind::Async)
104       .Case("attach", OpenACCClauseKind::Attach)
105       .Case("auto", OpenACCClauseKind::Auto)
106       .Case("bind", OpenACCClauseKind::Bind)
107       .Case("create", OpenACCClauseKind::Create)
108       .Case("pcreate", OpenACCClauseKind::PCreate)
109       .Case("present_or_create", OpenACCClauseKind::PresentOrCreate)
110       .Case("collapse", OpenACCClauseKind::Collapse)
111       .Case("copy", OpenACCClauseKind::Copy)
112       .Case("pcopy", OpenACCClauseKind::PCopy)
113       .Case("present_or_copy", OpenACCClauseKind::PresentOrCopy)
114       .Case("copyin", OpenACCClauseKind::CopyIn)
115       .Case("pcopyin", OpenACCClauseKind::PCopyIn)
116       .Case("present_or_copyin", OpenACCClauseKind::PresentOrCopyIn)
117       .Case("copyout", OpenACCClauseKind::CopyOut)
118       .Case("pcopyout", OpenACCClauseKind::PCopyOut)
119       .Case("present_or_copyout", OpenACCClauseKind::PresentOrCopyOut)
120       .Case("default", OpenACCClauseKind::Default)
121       .Case("default_async", OpenACCClauseKind::DefaultAsync)
122       .Case("delete", OpenACCClauseKind::Delete)
123       .Case("detach", OpenACCClauseKind::Detach)
124       .Case("device", OpenACCClauseKind::Device)
125       .Case("device_num", OpenACCClauseKind::DeviceNum)
126       .Case("device_resident", OpenACCClauseKind::DeviceResident)
127       .Case("device_type", OpenACCClauseKind::DeviceType)
128       .Case("deviceptr", OpenACCClauseKind::DevicePtr)
129       .Case("dtype", OpenACCClauseKind::DType)
130       .Case("finalize", OpenACCClauseKind::Finalize)
131       .Case("firstprivate", OpenACCClauseKind::FirstPrivate)
132       .Case("gang", OpenACCClauseKind::Gang)
133       .Case("host", OpenACCClauseKind::Host)
134       .Case("if", OpenACCClauseKind::If)
135       .Case("if_present", OpenACCClauseKind::IfPresent)
136       .Case("independent", OpenACCClauseKind::Independent)
137       .Case("link", OpenACCClauseKind::Link)
138       .Case("no_create", OpenACCClauseKind::NoCreate)
139       .Case("num_gangs", OpenACCClauseKind::NumGangs)
140       .Case("num_workers", OpenACCClauseKind::NumWorkers)
141       .Case("nohost", OpenACCClauseKind::NoHost)
142       .Case("present", OpenACCClauseKind::Present)
143       .Case("private", OpenACCClauseKind::Private)
144       .Case("reduction", OpenACCClauseKind::Reduction)
145       .Case("self", OpenACCClauseKind::Self)
146       .Case("seq", OpenACCClauseKind::Seq)
147       .Case("tile", OpenACCClauseKind::Tile)
148       .Case("use_device", OpenACCClauseKind::UseDevice)
149       .Case("vector", OpenACCClauseKind::Vector)
150       .Case("vector_length", OpenACCClauseKind::VectorLength)
151       .Case("wait", OpenACCClauseKind::Wait)
152       .Case("worker", OpenACCClauseKind::Worker)
153       .Default(OpenACCClauseKind::Invalid);
154 }
155 
156 // Since 'atomic' is effectively a compound directive, this will decode the
157 // second part of the directive.
getOpenACCAtomicKind(Token Tok)158 OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
159   if (!Tok.is(tok::identifier))
160     return OpenACCAtomicKind::None;
161   return llvm::StringSwitch<OpenACCAtomicKind>(
162              Tok.getIdentifierInfo()->getName())
163       .Case("read", OpenACCAtomicKind::Read)
164       .Case("write", OpenACCAtomicKind::Write)
165       .Case("update", OpenACCAtomicKind::Update)
166       .Case("capture", OpenACCAtomicKind::Capture)
167       .Default(OpenACCAtomicKind::None);
168 }
169 
getOpenACCDefaultClauseKind(Token Tok)170 OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) {
171   if (!Tok.is(tok::identifier))
172     return OpenACCDefaultClauseKind::Invalid;
173 
174   return llvm::StringSwitch<OpenACCDefaultClauseKind>(
175              Tok.getIdentifierInfo()->getName())
176       .Case("none", OpenACCDefaultClauseKind::None)
177       .Case("present", OpenACCDefaultClauseKind::Present)
178       .Default(OpenACCDefaultClauseKind::Invalid);
179 }
180 
181 enum class OpenACCSpecialTokenKind {
182   ReadOnly,
183   DevNum,
184   Queues,
185   Zero,
186   Force,
187   Num,
188   Length,
189   Dim,
190   Static,
191 };
192 
isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind,Token Tok)193 bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {
194   if (Tok.is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static)
195     return true;
196 
197   if (!Tok.is(tok::identifier))
198     return false;
199 
200   switch (Kind) {
201   case OpenACCSpecialTokenKind::ReadOnly:
202     return Tok.getIdentifierInfo()->isStr("readonly");
203   case OpenACCSpecialTokenKind::DevNum:
204     return Tok.getIdentifierInfo()->isStr("devnum");
205   case OpenACCSpecialTokenKind::Queues:
206     return Tok.getIdentifierInfo()->isStr("queues");
207   case OpenACCSpecialTokenKind::Zero:
208     return Tok.getIdentifierInfo()->isStr("zero");
209   case OpenACCSpecialTokenKind::Force:
210     return Tok.getIdentifierInfo()->isStr("force");
211   case OpenACCSpecialTokenKind::Num:
212     return Tok.getIdentifierInfo()->isStr("num");
213   case OpenACCSpecialTokenKind::Length:
214     return Tok.getIdentifierInfo()->isStr("length");
215   case OpenACCSpecialTokenKind::Dim:
216     return Tok.getIdentifierInfo()->isStr("dim");
217   case OpenACCSpecialTokenKind::Static:
218     return Tok.getIdentifierInfo()->isStr("static");
219   }
220   llvm_unreachable("Unknown 'Kind' Passed");
221 }
222 
223 /// Used for cases where we have a token we want to check against an
224 /// 'identifier-like' token, but don't want to give awkward error messages in
225 /// cases where it is accidentially a keyword.
isTokenIdentifierOrKeyword(Parser & P,Token Tok)226 bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) {
227   if (Tok.is(tok::identifier))
228     return true;
229 
230   if (!Tok.isAnnotation() && Tok.getIdentifierInfo() &&
231       Tok.getIdentifierInfo()->isKeyword(P.getLangOpts()))
232     return true;
233 
234   return false;
235 }
236 
237 /// Parses and consumes an identifer followed immediately by a single colon, and
238 /// diagnoses if it is not the 'special token' kind that we require. Used when
239 /// the tag is the only valid value.
240 /// Return 'true' if the special token was matched, false if no special token,
241 /// or an invalid special token was found.
242 template <typename DirOrClauseTy>
tryParseAndConsumeSpecialTokenKind(Parser & P,OpenACCSpecialTokenKind Kind,DirOrClauseTy DirOrClause)243 bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind,
244                                         DirOrClauseTy DirOrClause) {
245   Token IdentTok = P.getCurToken();
246   // If this is an identifier-like thing followed by ':', it is one of the
247   // OpenACC 'special' name tags, so consume it.
248   if (isTokenIdentifierOrKeyword(P, IdentTok) && P.NextToken().is(tok::colon)) {
249     P.ConsumeToken();
250     P.ConsumeToken();
251 
252     if (!isOpenACCSpecialToken(Kind, IdentTok)) {
253       P.Diag(IdentTok, diag::err_acc_invalid_tag_kind)
254           << IdentTok.getIdentifierInfo() << DirOrClause
255           << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>;
256       return false;
257     }
258 
259     return true;
260   }
261 
262   return false;
263 }
264 
isOpenACCDirectiveKind(OpenACCDirectiveKind Kind,Token Tok)265 bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
266   if (!Tok.is(tok::identifier))
267     return false;
268 
269   switch (Kind) {
270   case OpenACCDirectiveKind::Parallel:
271     return Tok.getIdentifierInfo()->isStr("parallel");
272   case OpenACCDirectiveKind::Serial:
273     return Tok.getIdentifierInfo()->isStr("serial");
274   case OpenACCDirectiveKind::Kernels:
275     return Tok.getIdentifierInfo()->isStr("kernels");
276   case OpenACCDirectiveKind::Data:
277     return Tok.getIdentifierInfo()->isStr("data");
278   case OpenACCDirectiveKind::HostData:
279     return Tok.getIdentifierInfo()->isStr("host_data");
280   case OpenACCDirectiveKind::Loop:
281     return Tok.getIdentifierInfo()->isStr("loop");
282   case OpenACCDirectiveKind::Cache:
283     return Tok.getIdentifierInfo()->isStr("cache");
284 
285   case OpenACCDirectiveKind::ParallelLoop:
286   case OpenACCDirectiveKind::SerialLoop:
287   case OpenACCDirectiveKind::KernelsLoop:
288   case OpenACCDirectiveKind::EnterData:
289   case OpenACCDirectiveKind::ExitData:
290     return false;
291 
292   case OpenACCDirectiveKind::Atomic:
293     return Tok.getIdentifierInfo()->isStr("atomic");
294   case OpenACCDirectiveKind::Routine:
295     return Tok.getIdentifierInfo()->isStr("routine");
296   case OpenACCDirectiveKind::Declare:
297     return Tok.getIdentifierInfo()->isStr("declare");
298   case OpenACCDirectiveKind::Init:
299     return Tok.getIdentifierInfo()->isStr("init");
300   case OpenACCDirectiveKind::Shutdown:
301     return Tok.getIdentifierInfo()->isStr("shutdown");
302   case OpenACCDirectiveKind::Set:
303     return Tok.getIdentifierInfo()->isStr("set");
304   case OpenACCDirectiveKind::Update:
305     return Tok.getIdentifierInfo()->isStr("update");
306   case OpenACCDirectiveKind::Wait:
307     return Tok.getIdentifierInfo()->isStr("wait");
308   case OpenACCDirectiveKind::Invalid:
309     return false;
310   }
311   llvm_unreachable("Unknown 'Kind' Passed");
312 }
313 
ParseReductionOperator(Parser & P)314 OpenACCReductionOperator ParseReductionOperator(Parser &P) {
315   // If there is no colon, treat as if the reduction operator was missing, else
316   // we probably will not recover from it in the case where an expression starts
317   // with one of the operator tokens.
318   if (P.NextToken().isNot(tok::colon)) {
319     P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator);
320     return OpenACCReductionOperator::Invalid;
321   }
322   Token ReductionKindTok = P.getCurToken();
323   // Consume both the kind and the colon.
324   P.ConsumeToken();
325   P.ConsumeToken();
326 
327   switch (ReductionKindTok.getKind()) {
328   case tok::plus:
329     return OpenACCReductionOperator::Addition;
330   case tok::star:
331     return OpenACCReductionOperator::Multiplication;
332   case tok::amp:
333     return OpenACCReductionOperator::BitwiseAnd;
334   case tok::pipe:
335     return OpenACCReductionOperator::BitwiseOr;
336   case tok::caret:
337     return OpenACCReductionOperator::BitwiseXOr;
338   case tok::ampamp:
339     return OpenACCReductionOperator::And;
340   case tok::pipepipe:
341     return OpenACCReductionOperator::Or;
342   case tok::identifier:
343     if (ReductionKindTok.getIdentifierInfo()->isStr("max"))
344       return OpenACCReductionOperator::Max;
345     if (ReductionKindTok.getIdentifierInfo()->isStr("min"))
346       return OpenACCReductionOperator::Min;
347     [[fallthrough]];
348   default:
349     P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
350     return OpenACCReductionOperator::Invalid;
351   }
352   llvm_unreachable("Reduction op token kind not caught by 'default'?");
353 }
354 
355 /// Used for cases where we expect an identifier-like token, but don't want to
356 /// give awkward error messages in cases where it is accidentially a keyword.
expectIdentifierOrKeyword(Parser & P)357 bool expectIdentifierOrKeyword(Parser &P) {
358   Token Tok = P.getCurToken();
359 
360   if (isTokenIdentifierOrKeyword(P, Tok))
361     return false;
362 
363   P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
364   return true;
365 }
366 
367 OpenACCDirectiveKind
ParseOpenACCEnterExitDataDirective(Parser & P,Token FirstTok,OpenACCDirectiveKindEx ExtDirKind)368 ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
369                                    OpenACCDirectiveKindEx ExtDirKind) {
370   Token SecondTok = P.getCurToken();
371 
372   if (SecondTok.isAnnotation()) {
373     P.Diag(FirstTok, diag::err_acc_invalid_directive)
374         << 0 << FirstTok.getIdentifierInfo();
375     return OpenACCDirectiveKind::Invalid;
376   }
377 
378   // Consume the second name anyway, this way we can continue on without making
379   // this oddly look like a clause.
380   P.ConsumeAnyToken();
381 
382   if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) {
383     if (!SecondTok.is(tok::identifier))
384       P.Diag(SecondTok, diag::err_expected) << tok::identifier;
385     else
386       P.Diag(FirstTok, diag::err_acc_invalid_directive)
387           << 1 << FirstTok.getIdentifierInfo()->getName()
388           << SecondTok.getIdentifierInfo()->getName();
389     return OpenACCDirectiveKind::Invalid;
390   }
391 
392   return ExtDirKind == OpenACCDirectiveKindEx::Enter
393              ? OpenACCDirectiveKind::EnterData
394              : OpenACCDirectiveKind::ExitData;
395 }
396 
ParseOpenACCAtomicKind(Parser & P)397 OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) {
398   Token AtomicClauseToken = P.getCurToken();
399 
400   // #pragma acc atomic is equivilent to update:
401   if (AtomicClauseToken.isAnnotation())
402     return OpenACCAtomicKind::None;
403 
404   OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken);
405 
406   // If this isn't a valid atomic-kind, don't consume the token, and treat the
407   // rest as a clause list, which despite there being no permissible clauses,
408   // will diagnose as a clause.
409   if (AtomicKind != OpenACCAtomicKind::None)
410     P.ConsumeToken();
411 
412   return AtomicKind;
413 }
414 
415 // Parse and consume the tokens for OpenACC Directive/Construct kinds.
ParseOpenACCDirectiveKind(Parser & P)416 OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
417   Token FirstTok = P.getCurToken();
418 
419   // Just #pragma acc can get us immediately to the end, make sure we don't
420   // introspect on the spelling before then.
421   if (FirstTok.isNot(tok::identifier)) {
422     P.Diag(FirstTok, diag::err_acc_missing_directive);
423 
424     if (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
425       P.ConsumeAnyToken();
426 
427     return OpenACCDirectiveKind::Invalid;
428   }
429 
430   P.ConsumeToken();
431 
432   OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok);
433 
434   // OpenACCDirectiveKindEx is meant to be an extended list
435   // over OpenACCDirectiveKind, so any value below Invalid is one of the
436   // OpenACCDirectiveKind values.  This switch takes care of all of the extra
437   // parsing required for the Extended values.  At the end of this block,
438   // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can
439   // immediately cast it and use it as that.
440   if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) {
441     switch (ExDirKind) {
442     case OpenACCDirectiveKindEx::Invalid: {
443       P.Diag(FirstTok, diag::err_acc_invalid_directive)
444           << 0 << FirstTok.getIdentifierInfo();
445       return OpenACCDirectiveKind::Invalid;
446     }
447     case OpenACCDirectiveKindEx::Enter:
448     case OpenACCDirectiveKindEx::Exit:
449       return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind);
450     }
451   }
452 
453   OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind);
454 
455   // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any
456   // other attempt at a combined construct will be diagnosed as an invalid
457   // clause.
458   Token SecondTok = P.getCurToken();
459   if (!SecondTok.isAnnotation() &&
460       isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) {
461     switch (DirKind) {
462     default:
463       // Nothing to do except in the below cases, as they should be diagnosed as
464       // a clause.
465       break;
466     case OpenACCDirectiveKind::Parallel:
467       P.ConsumeToken();
468       return OpenACCDirectiveKind::ParallelLoop;
469     case OpenACCDirectiveKind::Serial:
470       P.ConsumeToken();
471       return OpenACCDirectiveKind::SerialLoop;
472     case OpenACCDirectiveKind::Kernels:
473       P.ConsumeToken();
474       return OpenACCDirectiveKind::KernelsLoop;
475     }
476   }
477 
478   return DirKind;
479 }
480 
481 enum ClauseParensKind {
482   None,
483   Optional,
484   Required
485 };
486 
getClauseParensKind(OpenACCDirectiveKind DirKind,OpenACCClauseKind Kind)487 ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
488                                      OpenACCClauseKind Kind) {
489   switch (Kind) {
490   case OpenACCClauseKind::Self:
491     return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required
492                                                    : ClauseParensKind::Optional;
493   case OpenACCClauseKind::Async:
494   case OpenACCClauseKind::Worker:
495   case OpenACCClauseKind::Vector:
496   case OpenACCClauseKind::Gang:
497   case OpenACCClauseKind::Wait:
498     return ClauseParensKind::Optional;
499 
500   case OpenACCClauseKind::Default:
501   case OpenACCClauseKind::If:
502   case OpenACCClauseKind::Create:
503   case OpenACCClauseKind::PCreate:
504   case OpenACCClauseKind::PresentOrCreate:
505   case OpenACCClauseKind::Copy:
506   case OpenACCClauseKind::PCopy:
507   case OpenACCClauseKind::PresentOrCopy:
508   case OpenACCClauseKind::CopyIn:
509   case OpenACCClauseKind::PCopyIn:
510   case OpenACCClauseKind::PresentOrCopyIn:
511   case OpenACCClauseKind::CopyOut:
512   case OpenACCClauseKind::PCopyOut:
513   case OpenACCClauseKind::PresentOrCopyOut:
514   case OpenACCClauseKind::UseDevice:
515   case OpenACCClauseKind::NoCreate:
516   case OpenACCClauseKind::Present:
517   case OpenACCClauseKind::DevicePtr:
518   case OpenACCClauseKind::Attach:
519   case OpenACCClauseKind::Detach:
520   case OpenACCClauseKind::Private:
521   case OpenACCClauseKind::FirstPrivate:
522   case OpenACCClauseKind::Delete:
523   case OpenACCClauseKind::DeviceResident:
524   case OpenACCClauseKind::Device:
525   case OpenACCClauseKind::Link:
526   case OpenACCClauseKind::Host:
527   case OpenACCClauseKind::Reduction:
528   case OpenACCClauseKind::Collapse:
529   case OpenACCClauseKind::Bind:
530   case OpenACCClauseKind::VectorLength:
531   case OpenACCClauseKind::NumGangs:
532   case OpenACCClauseKind::NumWorkers:
533   case OpenACCClauseKind::DeviceNum:
534   case OpenACCClauseKind::DefaultAsync:
535   case OpenACCClauseKind::DeviceType:
536   case OpenACCClauseKind::DType:
537   case OpenACCClauseKind::Tile:
538     return ClauseParensKind::Required;
539 
540   case OpenACCClauseKind::Shortloop:
541     llvm_unreachable("Shortloop shouldn't be generated in clang");
542   case OpenACCClauseKind::Auto:
543   case OpenACCClauseKind::Finalize:
544   case OpenACCClauseKind::IfPresent:
545   case OpenACCClauseKind::Independent:
546   case OpenACCClauseKind::Invalid:
547   case OpenACCClauseKind::NoHost:
548   case OpenACCClauseKind::Seq:
549     return ClauseParensKind::None;
550   }
551   llvm_unreachable("Unhandled clause kind");
552 }
553 
ClauseHasOptionalParens(OpenACCDirectiveKind DirKind,OpenACCClauseKind Kind)554 bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind,
555                              OpenACCClauseKind Kind) {
556   return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
557 }
558 
ClauseHasRequiredParens(OpenACCDirectiveKind DirKind,OpenACCClauseKind Kind)559 bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind,
560                              OpenACCClauseKind Kind) {
561   return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required;
562 }
563 
564 // Skip until we see the end of pragma token, but don't consume it. This is us
565 // just giving up on the rest of the pragma so we can continue executing. We
566 // have to do this because 'SkipUntil' considers paren balancing, which isn't
567 // what we want.
SkipUntilEndOfDirective(Parser & P)568 void SkipUntilEndOfDirective(Parser &P) {
569   while (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
570     P.ConsumeAnyToken();
571 }
572 
doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind)573 bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) {
574   switch (DirKind) {
575   case OpenACCDirectiveKind::Routine:
576     // FIXME: Routine MIGHT end up needing to be 'true' here, as it needs a way
577     // to capture a lambda-expression on the next line.
578   case OpenACCDirectiveKind::Cache:
579   case OpenACCDirectiveKind::Declare:
580   case OpenACCDirectiveKind::Set:
581   case OpenACCDirectiveKind::EnterData:
582   case OpenACCDirectiveKind::ExitData:
583   case OpenACCDirectiveKind::Wait:
584   case OpenACCDirectiveKind::Init:
585   case OpenACCDirectiveKind::Shutdown:
586   case OpenACCDirectiveKind::Update:
587   case OpenACCDirectiveKind::Invalid:
588     return false;
589   case OpenACCDirectiveKind::Parallel:
590   case OpenACCDirectiveKind::Serial:
591   case OpenACCDirectiveKind::Kernels:
592   case OpenACCDirectiveKind::ParallelLoop:
593   case OpenACCDirectiveKind::SerialLoop:
594   case OpenACCDirectiveKind::KernelsLoop:
595   case OpenACCDirectiveKind::Loop:
596   case OpenACCDirectiveKind::Data:
597   case OpenACCDirectiveKind::HostData:
598   case OpenACCDirectiveKind::Atomic:
599     return true;
600   }
601   llvm_unreachable("Unhandled directive->assoc stmt");
602 }
603 
getOpenACCScopeFlags(OpenACCDirectiveKind DirKind)604 unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) {
605   switch (DirKind) {
606   case OpenACCDirectiveKind::Parallel:
607   case OpenACCDirectiveKind::Serial:
608   case OpenACCDirectiveKind::Kernels:
609     // Mark this as a BreakScope/ContinueScope as well as a compute construct
610     // so that we can diagnose trying to 'break'/'continue' inside of one.
611     return Scope::BreakScope | Scope::ContinueScope |
612            Scope::OpenACCComputeConstructScope;
613   case OpenACCDirectiveKind::ParallelLoop:
614   case OpenACCDirectiveKind::SerialLoop:
615   case OpenACCDirectiveKind::KernelsLoop:
616     // Mark this as a BreakScope/ContinueScope as well as a compute construct
617     // so that we can diagnose trying to 'break'/'continue' inside of one.
618     return Scope::BreakScope | Scope::ContinueScope |
619            Scope::OpenACCComputeConstructScope |
620            Scope::OpenACCLoopConstructScope;
621   case OpenACCDirectiveKind::Loop:
622     return Scope::OpenACCLoopConstructScope;
623   case OpenACCDirectiveKind::Data:
624   case OpenACCDirectiveKind::EnterData:
625   case OpenACCDirectiveKind::ExitData:
626   case OpenACCDirectiveKind::HostData:
627   case OpenACCDirectiveKind::Wait:
628   case OpenACCDirectiveKind::Init:
629   case OpenACCDirectiveKind::Shutdown:
630   case OpenACCDirectiveKind::Cache:
631   case OpenACCDirectiveKind::Atomic:
632   case OpenACCDirectiveKind::Declare:
633   case OpenACCDirectiveKind::Routine:
634   case OpenACCDirectiveKind::Set:
635   case OpenACCDirectiveKind::Update:
636     return 0;
637   case OpenACCDirectiveKind::Invalid:
638     llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
639   }
640   llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
641 }
642 
643 } // namespace
644 
OpenACCCanContinue()645 Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
646   return {nullptr, OpenACCParseCanContinue::Can};
647 }
648 
OpenACCCannotContinue()649 Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
650   return {nullptr, OpenACCParseCanContinue::Cannot};
651 }
652 
OpenACCSuccess(OpenACCClause * Clause)653 Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {
654   return {Clause, OpenACCParseCanContinue::Can};
655 }
656 
ParseOpenACCConditionExpr()657 ExprResult Parser::ParseOpenACCConditionExpr() {
658   // FIXME: It isn't clear if the spec saying 'condition' means the same as
659   // it does in an if/while/etc (See ParseCXXCondition), however as it was
660   // written with Fortran/C in mind, we're going to assume it just means an
661   // 'expression evaluating to boolean'.
662   ExprResult ER = ParseExpression();
663 
664   if (!ER.isUsable())
665     return ER;
666 
667   Sema::ConditionResult R =
668       getActions().ActOnCondition(getCurScope(), ER.get()->getExprLoc(),
669                                   ER.get(), Sema::ConditionKind::Boolean);
670 
671   return R.isInvalid() ? ExprError() : R.get().second;
672 }
673 
tryParseModifierList(OpenACCClauseKind CK)674 OpenACCModifierKind Parser::tryParseModifierList(OpenACCClauseKind CK) {
675   // Use the tentative parsing to decide whether we are a comma-delmited list of
676   // identifers ending in a colon so we can do an actual parse with diagnostics.
677   {
678     RevertingTentativeParsingAction TPA{*this};
679     // capture any <ident><comma> pairs.
680     while (isTokenIdentifierOrKeyword(*this, getCurToken()) &&
681            NextToken().is(tok::comma)) {
682       ConsumeToken();
683       ConsumeToken();
684     }
685 
686     if (!isTokenIdentifierOrKeyword(*this, getCurToken()) ||
687         !NextToken().is(tok::colon)) {
688       // No modifiers as this isn't a valid modifier-list.
689       return OpenACCModifierKind::Invalid;
690     }
691   }
692 
693   auto GetModKind = [](Token T) {
694     return StringSwitch<OpenACCModifierKind>(T.getIdentifierInfo()->getName())
695         .Case("always", OpenACCModifierKind::Always)
696         .Case("alwaysin", OpenACCModifierKind::AlwaysIn)
697         .Case("alwaysout", OpenACCModifierKind::AlwaysOut)
698         .Case("readonly", OpenACCModifierKind::Readonly)
699         .Case("zero", OpenACCModifierKind::Zero)
700         .Case("capture", OpenACCModifierKind::Capture)
701         .Default(OpenACCModifierKind::Invalid);
702   };
703 
704   OpenACCModifierKind CurModList = OpenACCModifierKind::Invalid;
705   auto ConsumeModKind = [&]() {
706     Token IdentToken = getCurToken();
707     OpenACCModifierKind NewKind = GetModKind(IdentToken);
708 
709     if (NewKind == OpenACCModifierKind::Invalid)
710       Diag(IdentToken.getLocation(), diag::err_acc_modifier)
711           << diag::ACCModifier::Unknown << IdentToken.getIdentifierInfo() << CK;
712     else if ((NewKind & CurModList) != OpenACCModifierKind::Invalid)
713       Diag(IdentToken.getLocation(), diag::err_acc_modifier)
714           << diag::ACCModifier::Duplicate << IdentToken.getIdentifierInfo()
715           << CK;
716     else
717       CurModList |= NewKind;
718 
719     // Consumes the identifier.
720     ConsumeToken();
721     // Consumes the comma or colon.
722     ConsumeToken();
723   };
724 
725   // Inspect all but the last item. We inspected enough to know that our current
726   // token is the identifier-like thing, so just check for the comma.
727   while (NextToken().is(tok::comma))
728     ConsumeModKind();
729 
730   // Above we confirmed that this should be correct/we should be on the last
731   // item.
732   ConsumeModKind();
733 
734   return CurModList;
735 }
736 
737 SmallVector<OpenACCClause *>
ParseOpenACCClauseList(OpenACCDirectiveKind DirKind)738 Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
739   SmallVector<OpenACCClause *> Clauses;
740   bool FirstClause = true;
741   while (getCurToken().isNot(tok::annot_pragma_openacc_end)) {
742     // Comma is optional in a clause-list.
743     if (!FirstClause && getCurToken().is(tok::comma))
744       ConsumeToken();
745     FirstClause = false;
746 
747     OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind);
748     if (OpenACCClause *Clause = Result.getPointer()) {
749       Clauses.push_back(Clause);
750     } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) {
751       // Recovering from a bad clause is really difficult, so we just give up on
752       // error.
753       SkipUntilEndOfDirective(*this);
754       return Clauses;
755     }
756   }
757   return Clauses;
758 }
759 
760 Parser::OpenACCIntExprParseResult
ParseOpenACCIntExpr(OpenACCDirectiveKind DK,OpenACCClauseKind CK,SourceLocation Loc)761 Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
762                             SourceLocation Loc) {
763   ExprResult ER = ParseAssignmentExpression();
764 
765   // If the actual parsing failed, we don't know the state of the parse, so
766   // don't try to continue.
767   if (!ER.isUsable())
768     return {ER, OpenACCParseCanContinue::Cannot};
769 
770   return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()),
771           OpenACCParseCanContinue::Can};
772 }
773 
ParseOpenACCIntExprList(OpenACCDirectiveKind DK,OpenACCClauseKind CK,SourceLocation Loc,llvm::SmallVectorImpl<Expr * > & IntExprs)774 bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK,
775                                      OpenACCClauseKind CK, SourceLocation Loc,
776                                      llvm::SmallVectorImpl<Expr *> &IntExprs) {
777   OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc);
778 
779   if (!CurResult.first.isUsable() &&
780       CurResult.second == OpenACCParseCanContinue::Cannot) {
781     SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
782               Parser::StopBeforeMatch);
783     return true;
784   }
785 
786   IntExprs.push_back(CurResult.first.get());
787 
788   while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
789     ExpectAndConsume(tok::comma);
790 
791     CurResult = ParseOpenACCIntExpr(DK, CK, Loc);
792 
793     if (!CurResult.first.isUsable() &&
794         CurResult.second == OpenACCParseCanContinue::Cannot) {
795       SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
796                 Parser::StopBeforeMatch);
797       return true;
798     }
799     IntExprs.push_back(CurResult.first.get());
800   }
801   return false;
802 }
803 
ParseOpenACCDeviceTypeList(llvm::SmallVector<IdentifierLoc> & Archs)804 bool Parser::ParseOpenACCDeviceTypeList(
805     llvm::SmallVector<IdentifierLoc> &Archs) {
806 
807   if (expectIdentifierOrKeyword(*this)) {
808     SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
809               Parser::StopBeforeMatch);
810     return true;
811   }
812   IdentifierInfo *Ident = getCurToken().getIdentifierInfo();
813   Archs.emplace_back(ConsumeToken(), Ident);
814 
815   while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
816     ExpectAndConsume(tok::comma);
817 
818     if (expectIdentifierOrKeyword(*this)) {
819       SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
820                 Parser::StopBeforeMatch);
821       return true;
822     }
823     Ident = getCurToken().getIdentifierInfo();
824     Archs.emplace_back(ConsumeToken(), Ident);
825   }
826   return false;
827 }
828 
ParseOpenACCSizeExpr(OpenACCClauseKind CK)829 ExprResult Parser::ParseOpenACCSizeExpr(OpenACCClauseKind CK) {
830   // The size-expr ends up being ambiguous when only looking at the current
831   // token, as it could be a deref of a variable/expression.
832   if (getCurToken().is(tok::star) &&
833       NextToken().isOneOf(tok::comma, tok::r_paren,
834                           tok::annot_pragma_openacc_end)) {
835     SourceLocation AsteriskLoc = ConsumeToken();
836     return getActions().OpenACC().ActOnOpenACCAsteriskSizeExpr(AsteriskLoc);
837   }
838 
839   ExprResult SizeExpr = ParseConstantExpression();
840 
841   if (!SizeExpr.isUsable())
842     return SizeExpr;
843 
844   SizeExpr = getActions().OpenACC().ActOnIntExpr(
845       OpenACCDirectiveKind::Invalid, CK, SizeExpr.get()->getBeginLoc(),
846       SizeExpr.get());
847 
848   return SizeExpr;
849 }
850 
ParseOpenACCSizeExprList(OpenACCClauseKind CK,llvm::SmallVectorImpl<Expr * > & SizeExprs)851 bool Parser::ParseOpenACCSizeExprList(
852     OpenACCClauseKind CK, llvm::SmallVectorImpl<Expr *> &SizeExprs) {
853   ExprResult SizeExpr = ParseOpenACCSizeExpr(CK);
854   if (!SizeExpr.isUsable()) {
855     SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
856               Parser::StopBeforeMatch);
857     return true;
858   }
859 
860   SizeExprs.push_back(SizeExpr.get());
861 
862   while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
863     ExpectAndConsume(tok::comma);
864 
865     SizeExpr = ParseOpenACCSizeExpr(CK);
866     if (!SizeExpr.isUsable()) {
867       SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
868                 Parser::StopBeforeMatch);
869       return true;
870     }
871     SizeExprs.push_back(SizeExpr.get());
872   }
873   return false;
874 }
875 
ParseOpenACCGangArg(SourceLocation GangLoc)876 Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
877 
878   if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) &&
879       NextToken().is(tok::colon)) {
880     // 'static' just takes a size-expr, which is an int-expr or an asterisk.
881     ConsumeToken();
882     ConsumeToken();
883     ExprResult Res = ParseOpenACCSizeExpr(OpenACCClauseKind::Gang);
884     return {OpenACCGangKind::Static, Res};
885   }
886 
887   if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) &&
888       NextToken().is(tok::colon)) {
889     ConsumeToken();
890     ConsumeToken();
891     // Parse this as a const-expression, and we'll check its integer-ness/value
892     // in CheckGangExpr.
893     ExprResult Res = ParseConstantExpression();
894     return {OpenACCGangKind::Dim, Res};
895   }
896 
897   if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) &&
898       NextToken().is(tok::colon)) {
899     ConsumeToken();
900     ConsumeToken();
901     // Fallthrough to the 'int-expr' handling for when 'num' is omitted.
902   }
903 
904   // This is just the 'num' case where 'num' is optional.
905   ExprResult Res = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
906                                        OpenACCClauseKind::Gang, GangLoc)
907                        .first;
908   return {OpenACCGangKind::Num, Res};
909 }
910 
ParseOpenACCGangArgList(SourceLocation GangLoc,llvm::SmallVectorImpl<OpenACCGangKind> & GKs,llvm::SmallVectorImpl<Expr * > & IntExprs)911 bool Parser::ParseOpenACCGangArgList(
912     SourceLocation GangLoc, llvm::SmallVectorImpl<OpenACCGangKind> &GKs,
913     llvm::SmallVectorImpl<Expr *> &IntExprs) {
914 
915   Parser::OpenACCGangArgRes Res = ParseOpenACCGangArg(GangLoc);
916   if (!Res.second.isUsable()) {
917     SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
918               Parser::StopBeforeMatch);
919     return true;
920   }
921 
922   GKs.push_back(Res.first);
923   IntExprs.push_back(Res.second.get());
924 
925   while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
926     ExpectAndConsume(tok::comma);
927 
928     Res = ParseOpenACCGangArg(GangLoc);
929     if (!Res.second.isUsable()) {
930       SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
931                 Parser::StopBeforeMatch);
932       return true;
933     }
934 
935     GKs.push_back(Res.first);
936     IntExprs.push_back(Res.second.get());
937   }
938   return false;
939 }
940 
941 namespace {
isUnsupportedExtensionClause(Token Tok)942 bool isUnsupportedExtensionClause(Token Tok) {
943   if (!Tok.is(tok::identifier))
944     return false;
945 
946   return Tok.getIdentifierInfo()->getName().starts_with("__");
947 }
948 } // namespace
949 
950 Parser::OpenACCClauseParseResult
ParseOpenACCClause(ArrayRef<const OpenACCClause * > ExistingClauses,OpenACCDirectiveKind DirKind)951 Parser::ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
952                            OpenACCDirectiveKind DirKind) {
953   // A number of clause names are actually keywords, so accept a keyword that
954   // can be converted to a name.
955   if (expectIdentifierOrKeyword(*this))
956     return OpenACCCannotContinue();
957 
958   OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken());
959 
960   if (isUnsupportedExtensionClause(getCurToken())) {
961     Diag(getCurToken(), diag::warn_acc_unsupported_extension_clause)
962         << getCurToken().getIdentifierInfo();
963 
964     // Extension methods optionally contain balanced token sequences, so we are
965     // going to parse this.
966     ConsumeToken(); // Consume the clause name.
967     BalancedDelimiterTracker Parens(*this, tok::l_paren,
968                                     tok::annot_pragma_openacc_end);
969     // Consume the optional parens and tokens inside of them.
970     if (!Parens.consumeOpen())
971       Parens.skipToEnd();
972 
973     return OpenACCCanContinue();
974   } else if (Kind == OpenACCClauseKind::Invalid) {
975     Diag(getCurToken(), diag::err_acc_invalid_clause)
976         << getCurToken().getIdentifierInfo();
977     return OpenACCCannotContinue();
978   }
979 
980   // Consume the clause name.
981   SourceLocation ClauseLoc = ConsumeToken();
982 
983   return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);
984 }
985 
ParseOpenACCClauseParams(ArrayRef<const OpenACCClause * > ExistingClauses,OpenACCDirectiveKind DirKind,OpenACCClauseKind ClauseKind,SourceLocation ClauseLoc)986 Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
987     ArrayRef<const OpenACCClause *> ExistingClauses,
988     OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind,
989     SourceLocation ClauseLoc) {
990   BalancedDelimiterTracker Parens(*this, tok::l_paren,
991                                   tok::annot_pragma_openacc_end);
992   SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc);
993 
994   if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
995     if (Parens.expectAndConsume()) {
996       // We are missing a paren, so assume that the person just forgot the
997       // parameter.  Return 'false' so we try to continue on and parse the next
998       // clause.
999       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
1000                 Parser::StopBeforeMatch);
1001       return OpenACCCanContinue();
1002     }
1003     ParsedClause.setLParenLoc(Parens.getOpenLocation());
1004 
1005     switch (ClauseKind) {
1006     case OpenACCClauseKind::Default: {
1007       Token DefKindTok = getCurToken();
1008 
1009       if (expectIdentifierOrKeyword(*this)) {
1010         Parens.skipToEnd();
1011         return OpenACCCanContinue();
1012       }
1013 
1014       ConsumeToken();
1015 
1016       OpenACCDefaultClauseKind DefKind =
1017           getOpenACCDefaultClauseKind(DefKindTok);
1018 
1019       if (DefKind == OpenACCDefaultClauseKind::Invalid) {
1020         Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
1021         Parens.skipToEnd();
1022         return OpenACCCanContinue();
1023       }
1024 
1025       ParsedClause.setDefaultDetails(DefKind);
1026       break;
1027     }
1028     case OpenACCClauseKind::If: {
1029       ExprResult CondExpr = ParseOpenACCConditionExpr();
1030       ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get()
1031                                                            : nullptr);
1032 
1033       if (CondExpr.isInvalid()) {
1034         Parens.skipToEnd();
1035         return OpenACCCanContinue();
1036       }
1037 
1038       break;
1039     }
1040     case OpenACCClauseKind::Copy:
1041     case OpenACCClauseKind::PCopy:
1042     case OpenACCClauseKind::PresentOrCopy:
1043     case OpenACCClauseKind::CopyIn:
1044     case OpenACCClauseKind::PCopyIn:
1045     case OpenACCClauseKind::PresentOrCopyIn:
1046     case OpenACCClauseKind::CopyOut:
1047     case OpenACCClauseKind::PCopyOut:
1048     case OpenACCClauseKind::PresentOrCopyOut:
1049     case OpenACCClauseKind::Create:
1050     case OpenACCClauseKind::PCreate:
1051     case OpenACCClauseKind::PresentOrCreate: {
1052       OpenACCModifierKind ModList = tryParseModifierList(ClauseKind);
1053       ParsedClause.setVarListDetails(ParseOpenACCVarList(DirKind, ClauseKind),
1054                                      ModList);
1055       break;
1056     }
1057     case OpenACCClauseKind::Reduction: {
1058       // If we're missing a clause-kind (or it is invalid), see if we can parse
1059       // the var-list anyway.
1060       OpenACCReductionOperator Op = ParseReductionOperator(*this);
1061       ParsedClause.setReductionDetails(
1062           Op, ParseOpenACCVarList(DirKind, ClauseKind));
1063       break;
1064     }
1065     case OpenACCClauseKind::Self:
1066       // The 'self' clause is a var-list instead of a 'condition' in the case of
1067       // the 'update' clause, so we have to handle it here.  Use an assert to
1068       // make sure we get the right differentiator.
1069       assert(DirKind == OpenACCDirectiveKind::Update);
1070       [[fallthrough]];
1071     case OpenACCClauseKind::Device:
1072     case OpenACCClauseKind::Host:
1073     case OpenACCClauseKind::DeviceResident:
1074     case OpenACCClauseKind::Link:
1075     case OpenACCClauseKind::Attach:
1076     case OpenACCClauseKind::Delete:
1077     case OpenACCClauseKind::Detach:
1078     case OpenACCClauseKind::DevicePtr:
1079     case OpenACCClauseKind::UseDevice:
1080     case OpenACCClauseKind::FirstPrivate:
1081     case OpenACCClauseKind::NoCreate:
1082     case OpenACCClauseKind::Present:
1083     case OpenACCClauseKind::Private:
1084       ParsedClause.setVarListDetails(ParseOpenACCVarList(DirKind, ClauseKind),
1085                                      OpenACCModifierKind::Invalid);
1086       break;
1087     case OpenACCClauseKind::Collapse: {
1088       bool HasForce = tryParseAndConsumeSpecialTokenKind(
1089           *this, OpenACCSpecialTokenKind::Force, ClauseKind);
1090       ExprResult LoopCount = ParseConstantExpression();
1091       if (LoopCount.isInvalid()) {
1092         Parens.skipToEnd();
1093         return OpenACCCanContinue();
1094       }
1095 
1096       LoopCount = getActions().OpenACC().ActOnIntExpr(
1097           OpenACCDirectiveKind::Invalid, ClauseKind,
1098           LoopCount.get()->getBeginLoc(), LoopCount.get());
1099 
1100       if (LoopCount.isInvalid()) {
1101         Parens.skipToEnd();
1102         return OpenACCCanContinue();
1103       }
1104 
1105       ParsedClause.setCollapseDetails(HasForce, LoopCount.get());
1106       break;
1107     }
1108     case OpenACCClauseKind::Bind: {
1109       ParsedClause.setBindDetails(ParseOpenACCBindClauseArgument());
1110 
1111       // We can create an 'empty' bind clause in the event of an error
1112       if (std::holds_alternative<std::monostate>(
1113               ParsedClause.getBindDetails())) {
1114         Parens.skipToEnd();
1115         return OpenACCCanContinue();
1116       }
1117       break;
1118     }
1119     case OpenACCClauseKind::NumGangs: {
1120       llvm::SmallVector<Expr *> IntExprs;
1121 
1122       if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid,
1123                                   OpenACCClauseKind::NumGangs, ClauseLoc,
1124                                   IntExprs)) {
1125         Parens.skipToEnd();
1126         return OpenACCCanContinue();
1127       }
1128       ParsedClause.setIntExprDetails(std::move(IntExprs));
1129       break;
1130     }
1131     case OpenACCClauseKind::NumWorkers:
1132     case OpenACCClauseKind::DeviceNum:
1133     case OpenACCClauseKind::DefaultAsync:
1134     case OpenACCClauseKind::VectorLength: {
1135       ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
1136                                                ClauseKind, ClauseLoc)
1137                                .first;
1138       if (IntExpr.isInvalid()) {
1139         Parens.skipToEnd();
1140         return OpenACCCanContinue();
1141       }
1142 
1143       ParsedClause.setIntExprDetails(IntExpr.get());
1144       break;
1145     }
1146     case OpenACCClauseKind::DType:
1147     case OpenACCClauseKind::DeviceType: {
1148       llvm::SmallVector<IdentifierLoc> Archs;
1149       if (getCurToken().is(tok::star)) {
1150         // FIXME: We want to mark that this is an 'everything else' type of
1151         // device_type in Sema.
1152         ParsedClause.setDeviceTypeDetails(
1153             {IdentifierLoc(ConsumeToken(), nullptr)});
1154       } else if (!ParseOpenACCDeviceTypeList(Archs)) {
1155         ParsedClause.setDeviceTypeDetails(std::move(Archs));
1156       } else {
1157         Parens.skipToEnd();
1158         return OpenACCCanContinue();
1159       }
1160       break;
1161     }
1162     case OpenACCClauseKind::Tile: {
1163       llvm::SmallVector<Expr *> SizeExprs;
1164       if (ParseOpenACCSizeExprList(OpenACCClauseKind::Tile, SizeExprs)) {
1165         Parens.skipToEnd();
1166         return OpenACCCanContinue();
1167       }
1168 
1169       ParsedClause.setIntExprDetails(std::move(SizeExprs));
1170       break;
1171     }
1172     default:
1173       llvm_unreachable("Not a required parens type?");
1174     }
1175 
1176     ParsedClause.setEndLoc(getCurToken().getLocation());
1177 
1178     if (Parens.consumeClose())
1179       return OpenACCCannotContinue();
1180 
1181   } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
1182     if (!Parens.consumeOpen()) {
1183       ParsedClause.setLParenLoc(Parens.getOpenLocation());
1184       switch (ClauseKind) {
1185       case OpenACCClauseKind::Self: {
1186         assert(DirKind != OpenACCDirectiveKind::Update);
1187         ExprResult CondExpr = ParseOpenACCConditionExpr();
1188         ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get()
1189                                                              : nullptr);
1190 
1191         if (CondExpr.isInvalid()) {
1192           Parens.skipToEnd();
1193           return OpenACCCanContinue();
1194         }
1195         break;
1196       }
1197       case OpenACCClauseKind::Vector:
1198       case OpenACCClauseKind::Worker: {
1199         tryParseAndConsumeSpecialTokenKind(*this,
1200                                            ClauseKind ==
1201                                                    OpenACCClauseKind::Vector
1202                                                ? OpenACCSpecialTokenKind::Length
1203                                                : OpenACCSpecialTokenKind::Num,
1204                                            ClauseKind);
1205         ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
1206                                                  ClauseKind, ClauseLoc)
1207                                  .first;
1208         if (IntExpr.isInvalid()) {
1209           Parens.skipToEnd();
1210           return OpenACCCanContinue();
1211         }
1212         ParsedClause.setIntExprDetails(IntExpr.get());
1213         break;
1214       }
1215       case OpenACCClauseKind::Async: {
1216         ExprResult AsyncArg =
1217             ParseOpenACCAsyncArgument(OpenACCDirectiveKind::Invalid,
1218                                       OpenACCClauseKind::Async, ClauseLoc)
1219                 .first;
1220         ParsedClause.setIntExprDetails(AsyncArg.isUsable() ? AsyncArg.get()
1221                                                            : nullptr);
1222         if (AsyncArg.isInvalid()) {
1223           Parens.skipToEnd();
1224           return OpenACCCanContinue();
1225         }
1226         break;
1227       }
1228       case OpenACCClauseKind::Gang: {
1229         llvm::SmallVector<OpenACCGangKind> GKs;
1230         llvm::SmallVector<Expr *> IntExprs;
1231         if (ParseOpenACCGangArgList(ClauseLoc, GKs, IntExprs)) {
1232           Parens.skipToEnd();
1233           return OpenACCCanContinue();
1234         }
1235         ParsedClause.setGangDetails(std::move(GKs), std::move(IntExprs));
1236         break;
1237       }
1238       case OpenACCClauseKind::Wait: {
1239         OpenACCWaitParseInfo Info =
1240             ParseOpenACCWaitArgument(ClauseLoc,
1241                                      /*IsDirective=*/false);
1242         if (Info.Failed) {
1243           Parens.skipToEnd();
1244           return OpenACCCanContinue();
1245         }
1246 
1247         ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc,
1248                                     std::move(Info.QueueIdExprs));
1249         break;
1250       }
1251       default:
1252         llvm_unreachable("Not an optional parens type?");
1253       }
1254       ParsedClause.setEndLoc(getCurToken().getLocation());
1255       if (Parens.consumeClose())
1256         return OpenACCCannotContinue();
1257     } else {
1258       // If we have optional parens, make sure we set the end-location to the
1259       // clause, as we are a 'single token' clause.
1260       ParsedClause.setEndLoc(ClauseLoc);
1261     }
1262   } else {
1263     ParsedClause.setEndLoc(ClauseLoc);
1264   }
1265   return OpenACCSuccess(
1266       Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause));
1267 }
1268 
1269 Parser::OpenACCIntExprParseResult
ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK,OpenACCClauseKind CK,SourceLocation Loc)1270 Parser::ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
1271                                   SourceLocation Loc) {
1272   return ParseOpenACCIntExpr(DK, CK, Loc);
1273 }
1274 
1275 Parser::OpenACCWaitParseInfo
ParseOpenACCWaitArgument(SourceLocation Loc,bool IsDirective)1276 Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
1277   OpenACCWaitParseInfo Result;
1278   // [devnum : int-expr : ]
1279   if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
1280       NextToken().is(tok::colon)) {
1281     // Consume devnum.
1282     ConsumeToken();
1283     // Consume colon.
1284     ConsumeToken();
1285 
1286     OpenACCIntExprParseResult Res = ParseOpenACCIntExpr(
1287         IsDirective ? OpenACCDirectiveKind::Wait
1288                     : OpenACCDirectiveKind::Invalid,
1289         IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait,
1290         Loc);
1291     if (Res.first.isInvalid() &&
1292         Res.second == OpenACCParseCanContinue::Cannot) {
1293       Result.Failed = true;
1294       return Result;
1295     }
1296 
1297     if (ExpectAndConsume(tok::colon)) {
1298       Result.Failed = true;
1299       return Result;
1300     }
1301 
1302     Result.DevNumExpr = Res.first.get();
1303   }
1304 
1305   // [ queues : ]
1306   if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
1307       NextToken().is(tok::colon)) {
1308     // Consume queues.
1309     Result.QueuesLoc = ConsumeToken();
1310     // Consume colon.
1311     ConsumeToken();
1312   }
1313 
1314 
1315 
1316   // OpenACC 3.3, section 2.16:
1317   // the term 'async-argument' means a nonnegative scalar integer expression, or
1318   // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined
1319   // in the C header file and the Fortran opacc module.
1320   OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1321       IsDirective ? OpenACCDirectiveKind::Wait
1322                   : OpenACCDirectiveKind::Invalid,
1323       IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait,
1324       Loc);
1325 
1326   if (Res.first.isInvalid() &&
1327       Res.second == OpenACCParseCanContinue::Cannot) {
1328     Result.Failed = true;
1329     return Result;
1330   }
1331 
1332   if (Res.first.isUsable())
1333     Result.QueueIdExprs.push_back(Res.first.get());
1334 
1335   while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1336     if (ExpectAndConsume(tok::comma)) {
1337       Result.Failed = true;
1338       return Result;
1339     }
1340 
1341     OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1342         IsDirective ? OpenACCDirectiveKind::Wait
1343                     : OpenACCDirectiveKind::Invalid,
1344         IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait,
1345         Loc);
1346 
1347     if (Res.first.isInvalid() &&
1348         Res.second == OpenACCParseCanContinue::Cannot) {
1349       Result.Failed = true;
1350       return Result;
1351     }
1352 
1353     if (Res.first.isUsable())
1354       Result.QueueIdExprs.push_back(Res.first.get());
1355   }
1356 
1357   return Result;
1358 }
1359 
ParseOpenACCIDExpression()1360 ExprResult Parser::ParseOpenACCIDExpression() {
1361   ExprResult Res;
1362   if (getLangOpts().CPlusPlus) {
1363     Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true);
1364   } else {
1365     // There isn't anything quite the same as ParseCXXIdExpression for C, so we
1366     // need to get the identifier, then call into Sema ourselves.
1367 
1368     if (Tok.isNot(tok::identifier)) {
1369       Diag(Tok, diag::err_expected) << tok::identifier;
1370       return ExprError();
1371     }
1372 
1373     Token FuncName = getCurToken();
1374     UnqualifiedId Name;
1375     CXXScopeSpec ScopeSpec;
1376     SourceLocation TemplateKWLoc;
1377     Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken());
1378 
1379     // Ensure this is a valid identifier. We don't accept causing implicit
1380     // function declarations per the spec, so always claim to not have trailing
1381     // L Paren.
1382     Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
1383                                     Name, /*HasTrailingLParen=*/false,
1384                                     /*isAddressOfOperand=*/false);
1385   }
1386 
1387   return Res;
1388 }
1389 
1390 std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
ParseOpenACCBindClauseArgument()1391 Parser::ParseOpenACCBindClauseArgument() {
1392   // OpenACC 3.3 section 2.15:
1393   // The bind clause specifies the name to use when calling the procedure on a
1394   // device other than the host. If the name is specified as an identifier, it
1395   // is called as if that name were specified in the language being compiled. If
1396   // the name is specified as a string, the string is used for the procedure
1397   // name unmodified.
1398   if (getCurToken().is(tok::r_paren)) {
1399     Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
1400     return std::monostate{};
1401   }
1402 
1403   if (getCurToken().is(tok::identifier)) {
1404     IdentifierInfo *II = getCurToken().getIdentifierInfo();
1405     ConsumeToken();
1406     return II;
1407   }
1408 
1409   if (!tok::isStringLiteral(getCurToken().getKind())) {
1410     Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
1411     return std::monostate{};
1412   }
1413 
1414   ExprResult Res = ParseStringLiteralExpression(
1415       /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true);
1416   if (!Res.isUsable())
1417     return std::monostate{};
1418   return cast<StringLiteral>(Res.get());
1419 }
1420 
ParseOpenACCVar(OpenACCDirectiveKind DK,OpenACCClauseKind CK)1421 Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCDirectiveKind DK,
1422                                                       OpenACCClauseKind CK) {
1423   OpenACCArraySectionRAII ArraySections(*this);
1424 
1425   getActions().OpenACC().ActOnStartParseVar(DK, CK);
1426   ExprResult Res = ParseAssignmentExpression();
1427 
1428   if (!Res.isUsable()) {
1429     getActions().OpenACC().ActOnInvalidParseVar();
1430     return {Res, OpenACCParseCanContinue::Cannot};
1431   }
1432 
1433   Res = getActions().OpenACC().ActOnVar(DK, CK, Res.get());
1434   return {Res, OpenACCParseCanContinue::Can};
1435 }
1436 
ParseOpenACCVarList(OpenACCDirectiveKind DK,OpenACCClauseKind CK)1437 llvm::SmallVector<Expr *> Parser::ParseOpenACCVarList(OpenACCDirectiveKind DK,
1438                                                       OpenACCClauseKind CK) {
1439   llvm::SmallVector<Expr *> Vars;
1440 
1441   auto [Res, CanContinue] = ParseOpenACCVar(DK, CK);
1442   if (Res.isUsable()) {
1443     Vars.push_back(Res.get());
1444   } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1445     SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch);
1446     return Vars;
1447   }
1448 
1449   while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1450     ExpectAndConsume(tok::comma);
1451 
1452     auto [Res, CanContinue] = ParseOpenACCVar(DK, CK);
1453 
1454     if (Res.isUsable()) {
1455       Vars.push_back(Res.get());
1456     } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1457       SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch);
1458       return Vars;
1459     }
1460   }
1461   return Vars;
1462 }
1463 
ParseOpenACCCacheVarList()1464 Parser::OpenACCCacheParseInfo Parser::ParseOpenACCCacheVarList() {
1465   // If this is the end of the line, just return 'false' and count on the close
1466   // paren diagnostic to catch the issue.
1467   if (getCurToken().isAnnotation())
1468     return {};
1469 
1470   OpenACCCacheParseInfo CacheInfo;
1471 
1472   SourceLocation ReadOnlyLoc = getCurToken().getLocation();
1473   // The VarList is an optional `readonly:` followed by a list of a variable
1474   // specifications. Consume something that looks like a 'tag', and diagnose if
1475   // it isn't 'readonly'.
1476   if (tryParseAndConsumeSpecialTokenKind(*this,
1477                                          OpenACCSpecialTokenKind::ReadOnly,
1478                                          OpenACCDirectiveKind::Cache))
1479     CacheInfo.ReadOnlyLoc = ReadOnlyLoc;
1480 
1481   // ParseOpenACCVarList should leave us before a r-paren, so no need to skip
1482   // anything here.
1483   CacheInfo.Vars = ParseOpenACCVarList(OpenACCDirectiveKind::Cache,
1484                                        OpenACCClauseKind::Invalid);
1485 
1486   return CacheInfo;
1487 }
1488 
1489 Parser::OpenACCDirectiveParseInfo
ParseOpenACCDirective()1490 Parser::ParseOpenACCDirective() {
1491   SourceLocation StartLoc = ConsumeAnnotationToken();
1492   SourceLocation DirLoc = getCurToken().getLocation();
1493   OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);
1494   Parser::OpenACCWaitParseInfo WaitInfo;
1495   Parser::OpenACCCacheParseInfo CacheInfo;
1496   OpenACCAtomicKind AtomicKind = OpenACCAtomicKind::None;
1497   ExprResult RoutineName;
1498 
1499   getActions().OpenACC().ActOnConstruct(DirKind, DirLoc);
1500 
1501   // Once we've parsed the construct/directive name, some have additional
1502   // specifiers that need to be taken care of. Atomic has an 'atomic-clause'
1503   // that needs to be parsed.
1504   if (DirKind == OpenACCDirectiveKind::Atomic)
1505     AtomicKind = ParseOpenACCAtomicKind(*this);
1506 
1507   // We've successfully parsed the construct/directive name, however a few of
1508   // the constructs have optional parens that contain further details.
1509   BalancedDelimiterTracker T(*this, tok::l_paren,
1510                              tok::annot_pragma_openacc_end);
1511 
1512   if (!T.consumeOpen()) {
1513     switch (DirKind) {
1514     default:
1515       Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren);
1516       T.skipToEnd();
1517       break;
1518     case OpenACCDirectiveKind::Routine: {
1519       // Routine has an optional paren-wrapped name of a function in the local
1520       // scope. We parse the name, emitting any diagnostics
1521       RoutineName = ParseOpenACCIDExpression();
1522       // If the routine name is invalid, just skip until the closing paren to
1523       // recover more gracefully.
1524       if (!RoutineName.isUsable()) {
1525         T.skipToEnd();
1526       } else {
1527         T.consumeClose();
1528         RoutineName =
1529             getActions().OpenACC().ActOnRoutineName(RoutineName.get());
1530       }
1531       break;
1532     }
1533     case OpenACCDirectiveKind::Cache:
1534       CacheInfo = ParseOpenACCCacheVarList();
1535       // The ParseOpenACCCacheVarList function manages to recover from failures,
1536       // so we can always consume the close.
1537       T.consumeClose();
1538       break;
1539     case OpenACCDirectiveKind::Wait:
1540       // OpenACC has an optional paren-wrapped 'wait-argument'.
1541       WaitInfo = ParseOpenACCWaitArgument(DirLoc, /*IsDirective=*/true);
1542       if (WaitInfo.Failed)
1543         T.skipToEnd();
1544       else
1545         T.consumeClose();
1546       break;
1547     }
1548   } else if (DirKind == OpenACCDirectiveKind::Cache) {
1549     // Cache's paren var-list is required, so error here if it isn't provided.
1550     // We know that the consumeOpen above left the first non-paren here, so
1551     // diagnose, then continue as if it was completely omitted.
1552     Diag(Tok, diag::err_expected) << tok::l_paren;
1553   }
1554 
1555   // Parses the list of clauses, if present, plus set up return value.
1556   OpenACCDirectiveParseInfo ParseInfo{DirKind,
1557                                       StartLoc,
1558                                       DirLoc,
1559                                       T.getOpenLocation(),
1560                                       T.getCloseLocation(),
1561                                       /*EndLoc=*/SourceLocation{},
1562                                       (DirKind == OpenACCDirectiveKind::Wait
1563                                            ? WaitInfo.QueuesLoc
1564                                            : CacheInfo.ReadOnlyLoc),
1565                                       AtomicKind,
1566                                       {},
1567                                       {}};
1568 
1569   if (DirKind == OpenACCDirectiveKind::Wait)
1570     ParseInfo.Exprs = WaitInfo.getAllExprs();
1571   else if (DirKind == OpenACCDirectiveKind::Cache)
1572     ParseInfo.Exprs = std::move(CacheInfo.Vars);
1573   else if (DirKind == OpenACCDirectiveKind::Routine && RoutineName.isUsable())
1574     ParseInfo.Exprs = llvm::SmallVector<Expr *>(1, RoutineName.get());
1575 
1576   ParseInfo.Clauses = ParseOpenACCClauseList(DirKind);
1577 
1578   assert(Tok.is(tok::annot_pragma_openacc_end) &&
1579          "Didn't parse all OpenACC Clauses");
1580   ParseInfo.EndLoc = ConsumeAnnotationToken();
1581   assert(ParseInfo.EndLoc.isValid() &&
1582          "Terminating annotation token not present");
1583 
1584   return ParseInfo;
1585 }
1586 
ParseOpenACCAfterRoutineDecl(AccessSpecifier & AS,ParsedAttributes & Attrs,DeclSpec::TST TagType,Decl * TagDecl,OpenACCDirectiveParseInfo & DirInfo)1587 Parser::DeclGroupPtrTy Parser::ParseOpenACCAfterRoutineDecl(
1588     AccessSpecifier &AS, ParsedAttributes &Attrs, DeclSpec::TST TagType,
1589     Decl *TagDecl, OpenACCDirectiveParseInfo &DirInfo) {
1590   assert(DirInfo.DirKind == OpenACCDirectiveKind::Routine);
1591 
1592   DeclGroupPtrTy Ptr;
1593   if (DirInfo.LParenLoc.isInvalid()) {
1594     if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1595       if (AS == AS_none) {
1596         // This is either an external declaration, or inside of a C struct. If
1597         // the latter, we have to diagnose if this is the 'implicit' named
1598         // version.
1599         if (TagType == DeclSpec::TST_unspecified) {
1600           ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
1601           MaybeParseCXX11Attributes(Attrs);
1602           ParsingDeclSpec PDS(*this);
1603           Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
1604         }
1605         // The only way we can have a 'none' access specifier that is in a
1606         // not-unspecified tag-type is a C struct. Member functions and
1607         // lambdas don't work in C, so we can just count on
1608         // ActonRoutineDeclDirective to recognize that Ptr is null and diagnose.
1609       } else {
1610         Ptr = ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType,
1611                                                         TagDecl);
1612       }
1613     }
1614   }
1615 
1616   return DeclGroupPtrTy::make(
1617       getActions().OpenACC().ActOnEndRoutineDeclDirective(
1618           DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1619           DirInfo.Exprs.empty() ? nullptr : DirInfo.Exprs.front(),
1620           DirInfo.RParenLoc, DirInfo.Clauses, DirInfo.EndLoc, Ptr));
1621 }
1622 
1623 StmtResult
ParseOpenACCAfterRoutineStmt(OpenACCDirectiveParseInfo & DirInfo)1624 Parser::ParseOpenACCAfterRoutineStmt(OpenACCDirectiveParseInfo &DirInfo) {
1625   assert(DirInfo.DirKind == OpenACCDirectiveKind::Routine);
1626   // We have to know the next statement for 1 of 2 reasons:
1627   // Routine without a name needs an associated DeclStmt.
1628   // Routine WITH a name needs to see if it is a DeclStmt to diagnose.
1629   StmtResult NextStmt = StmtEmpty();
1630 
1631   // Parse the next statement in the 'implicit' case, not in the 'named' case.
1632   // In the 'named' case we will use the creation of the next decl to determine
1633   // whether we should warn.
1634   if (DirInfo.LParenLoc.isInvalid()) {
1635     ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
1636     NextStmt = ParseStatement();
1637   }
1638 
1639   return getActions().OpenACC().ActOnEndRoutineStmtDirective(
1640       DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1641       DirInfo.Exprs.empty() ? nullptr : DirInfo.Exprs.front(),
1642       DirInfo.RParenLoc, DirInfo.Clauses, DirInfo.EndLoc, NextStmt.get());
1643 }
1644 
1645 Parser::DeclGroupPtrTy
ParseOpenACCDirectiveDecl(AccessSpecifier & AS,ParsedAttributes & Attrs,DeclSpec::TST TagType,Decl * TagDecl)1646 Parser::ParseOpenACCDirectiveDecl(AccessSpecifier &AS, ParsedAttributes &Attrs,
1647                                   DeclSpec::TST TagType, Decl *TagDecl) {
1648   assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1649 
1650   ParsingOpenACCDirectiveRAII DirScope(*this);
1651 
1652   OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1653 
1654   if (getActions().OpenACC().ActOnStartDeclDirective(
1655           DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
1656     return nullptr;
1657 
1658   if (DirInfo.DirKind == OpenACCDirectiveKind::Routine)
1659     return ParseOpenACCAfterRoutineDecl(AS, Attrs, TagType, TagDecl, DirInfo);
1660 
1661   return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective(
1662       DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1663       DirInfo.RParenLoc, DirInfo.EndLoc, DirInfo.Clauses));
1664 }
1665 
ParseOpenACCDirectiveStmt()1666 StmtResult Parser::ParseOpenACCDirectiveStmt() {
1667   assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1668 
1669   ParsingOpenACCDirectiveRAII DirScope(*this);
1670 
1671   OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1672   if (getActions().OpenACC().ActOnStartStmtDirective(
1673           DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
1674     return StmtError();
1675 
1676   if (DirInfo.DirKind == OpenACCDirectiveKind::Routine)
1677     return ParseOpenACCAfterRoutineStmt(DirInfo);
1678 
1679   StmtResult AssocStmt;
1680   if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {
1681     SemaOpenACC::AssociatedStmtRAII AssocStmtRAII(
1682         getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {},
1683         DirInfo.Clauses);
1684     ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
1685     ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind));
1686 
1687     AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(
1688         DirInfo.StartLoc, DirInfo.DirKind, DirInfo.AtomicKind, DirInfo.Clauses,
1689         ParseStatement());
1690   }
1691 
1692   return getActions().OpenACC().ActOnEndStmtDirective(
1693       DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1694       DirInfo.MiscLoc, DirInfo.Exprs, DirInfo.AtomicKind, DirInfo.RParenLoc,
1695       DirInfo.EndLoc, DirInfo.Clauses, AssocStmt);
1696 }
1697