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