clang  19.0.0git
ParseOpenACC.cpp
Go to the documentation of this file.
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 
16 #include "clang/Parse/Parser.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`.
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)
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.
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))
80 
81  // default is a keyword, so make sure we parse it correctly.
82  if (Tok.is(tok::kw_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))
92 
93  if (!Tok.is(tok::identifier))
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.
153 OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
154  if (!Tok.is(tok::identifier))
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 
165 OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) {
166  if (!Tok.is(tok::identifier))
168 
169  return llvm::StringSwitch<OpenACCDefaultClauseKind>(
170  Tok.getIdentifierInfo()->getName())
171  .Case("none", OpenACCDefaultClauseKind::None)
172  .Case("present", OpenACCDefaultClauseKind::Present)
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 
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");
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.
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>
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 
260 bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
261  if (!Tok.is(tok::identifier))
262  return false;
263 
264  switch (Kind) {
266  return Tok.getIdentifierInfo()->isStr("parallel");
268  return Tok.getIdentifierInfo()->isStr("serial");
270  return Tok.getIdentifierInfo()->isStr("kernels");
272  return Tok.getIdentifierInfo()->isStr("data");
274  return Tok.getIdentifierInfo()->isStr("host_data");
276  return Tok.getIdentifierInfo()->isStr("loop");
278  return Tok.getIdentifierInfo()->isStr("cache");
279 
285  return false;
286 
288  return Tok.getIdentifierInfo()->isStr("atomic");
290  return Tok.getIdentifierInfo()->isStr("routine");
292  return Tok.getIdentifierInfo()->isStr("declare");
294  return Tok.getIdentifierInfo()->isStr("init");
296  return Tok.getIdentifierInfo()->isStr("shutdown");
298  return Tok.getIdentifierInfo()->isStr("set");
300  return Tok.getIdentifierInfo()->isStr("update");
302  return Tok.getIdentifierInfo()->isStr("wait");
304  return false;
305  }
306  llvm_unreachable("Unknown 'Kind' Passed");
307 }
308 
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);
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:
325  case tok::star:
327  case tok::amp:
329  case tok::pipe:
331  case tok::caret:
333  case tok::ampamp:
335  case tok::pipepipe:
337  case tok::identifier:
338  if (ReductionKindTok.getIdentifierInfo()->isStr("max"))
340  if (ReductionKindTok.getIdentifierInfo()->isStr("min"))
342  [[fallthrough]];
343  default:
344  P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
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.
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 
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();
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();
385  }
386 
387  return ExtDirKind == OpenACCDirectiveKindEx::Enter
390 }
391 
392 OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) {
393  Token AtomicClauseToken = P.getCurToken();
394 
395  // #pragma acc atomic is equivilent to update:
396  if (AtomicClauseToken.isAnnotation())
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)
406 
407  P.ConsumeToken();
408  return AtomicKind;
409 }
410 
411 // Parse and consume the tokens for OpenACC Directive/Construct kinds.
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 
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();
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;
463  P.ConsumeToken();
466  P.ConsumeToken();
469  P.ConsumeToken();
471  }
472  }
473 
474  return DirKind;
475 }
476 
477 enum ClauseParensKind {
478  None,
479  Optional,
480  Required
481 };
482 
483 ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
485  switch (Kind) {
487  return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required
488  : ClauseParensKind::Optional;
494  return ClauseParensKind::Optional;
495 
534  return ClauseParensKind::Required;
535 
543  return ClauseParensKind::None;
544  }
545  llvm_unreachable("Unhandled clause kind");
546 }
547 
548 bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind,
550  return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
551 }
552 
553 bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind,
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.
562 void SkipUntilEndOfDirective(Parser &P) {
563  while (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
564  P.ConsumeAnyToken();
565 }
566 
567 bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) {
568  switch (DirKind) {
569  default:
570  return false;
574  return true;
575  }
576  llvm_unreachable("Unhandled directive->assoc stmt");
577 }
578 
579 unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) {
580  switch (DirKind) {
584  // Mark this as a BreakScope/ContinueScope as well as a compute construct
585  // so that we can diagnose trying to 'break'/'continue' inside of one.
589  llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
590  default:
591  break;
592  }
593  return 0;
594 }
595 
596 } // namespace
597 
598 Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
599  return {nullptr, OpenACCParseCanContinue::Can};
600 }
601 
602 Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
603  return {nullptr, OpenACCParseCanContinue::Cannot};
604 }
605 
606 Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {
607  return {Clause, OpenACCParseCanContinue::Can};
608 }
609 
610 ExprResult Parser::ParseOpenACCConditionExpr() {
611  // FIXME: It isn't clear if the spec saying 'condition' means the same as
612  // it does in an if/while/etc (See ParseCXXCondition), however as it was
613  // written with Fortran/C in mind, we're going to assume it just means an
614  // 'expression evaluating to boolean'.
615  ExprResult ER = getActions().CorrectDelayedTyposInExpr(ParseExpression());
616 
617  if (!ER.isUsable())
618  return ER;
619 
621  getActions().ActOnCondition(getCurScope(), ER.get()->getExprLoc(),
623 
624  return R.isInvalid() ? ExprError() : R.get().second;
625 }
626 
627 // OpenACC 3.3, section 1.7:
628 // To simplify the specification and convey appropriate constraint information,
629 // a pqr-list is a comma-separated list of pdr items. The one exception is a
630 // clause-list, which is a list of one or more clauses optionally separated by
631 // commas.
633 Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
635  bool FirstClause = true;
636  while (getCurToken().isNot(tok::annot_pragma_openacc_end)) {
637  // Comma is optional in a clause-list.
638  if (!FirstClause && getCurToken().is(tok::comma))
639  ConsumeToken();
640  FirstClause = false;
641 
642  OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind);
643  if (OpenACCClause *Clause = Result.getPointer()) {
644  Clauses.push_back(Clause);
645  } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) {
646  // Recovering from a bad clause is really difficult, so we just give up on
647  // error.
648  SkipUntilEndOfDirective(*this);
649  return Clauses;
650  }
651  }
652  return Clauses;
653 }
654 
655 Parser::OpenACCIntExprParseResult
656 Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
658  ExprResult ER = ParseAssignmentExpression();
659 
660  // If the actual parsing failed, we don't know the state of the parse, so
661  // don't try to continue.
662  if (!ER.isUsable())
663  return {ER, OpenACCParseCanContinue::Cannot};
664 
665  // Parsing can continue after the initial assignment expression parsing, so
666  // even if there was a typo, we can continue.
667  ER = getActions().CorrectDelayedTyposInExpr(ER);
668  if (!ER.isUsable())
669  return {ER, OpenACCParseCanContinue::Can};
670 
671  return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()),
672  OpenACCParseCanContinue::Can};
673 }
674 
675 bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK,
677  llvm::SmallVectorImpl<Expr *> &IntExprs) {
678  OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc);
679 
680  if (!CurResult.first.isUsable() &&
681  CurResult.second == OpenACCParseCanContinue::Cannot) {
682  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
684  return true;
685  }
686 
687  IntExprs.push_back(CurResult.first.get());
688 
689  while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
690  ExpectAndConsume(tok::comma);
691 
692  CurResult = ParseOpenACCIntExpr(DK, CK, Loc);
693 
694  if (!CurResult.first.isUsable() &&
695  CurResult.second == OpenACCParseCanContinue::Cannot) {
696  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
698  return true;
699  }
700  IntExprs.push_back(CurResult.first.get());
701  }
702  return false;
703 }
704 
705 /// OpenACC 3.3 Section 2.4:
706 /// The argument to the device_type clause is a comma-separated list of one or
707 /// more device architecture name identifiers, or an asterisk.
708 ///
709 /// The syntax of the device_type clause is
710 /// device_type( * )
711 /// device_type( device-type-list )
712 ///
713 /// The device_type clause may be abbreviated to dtype.
714 bool Parser::ParseOpenACCDeviceTypeList(
715  llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs) {
716 
717  if (expectIdentifierOrKeyword(*this)) {
718  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
720  return true;
721  }
722  IdentifierInfo *Ident = getCurToken().getIdentifierInfo();
723  Archs.emplace_back(Ident, ConsumeToken());
724 
725  while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
726  ExpectAndConsume(tok::comma);
727 
728  if (expectIdentifierOrKeyword(*this)) {
729  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
731  return true;
732  }
733  Ident = getCurToken().getIdentifierInfo();
734  Archs.emplace_back(Ident, ConsumeToken());
735  }
736  return false;
737 }
738 
739 /// OpenACC 3.3 Section 2.9:
740 /// size-expr is one of:
741 // *
742 // int-expr
743 // Note that this is specified under 'gang-arg-list', but also applies to 'tile'
744 // via reference.
745 bool Parser::ParseOpenACCSizeExpr() {
746  // FIXME: Ensure these are constant expressions.
747 
748  // The size-expr ends up being ambiguous when only looking at the current
749  // token, as it could be a deref of a variable/expression.
750  if (getCurToken().is(tok::star) &&
751  NextToken().isOneOf(tok::comma, tok::r_paren,
752  tok::annot_pragma_openacc_end)) {
753  ConsumeToken();
754  return false;
755  }
756 
757  return getActions()
758  .CorrectDelayedTyposInExpr(ParseAssignmentExpression())
759  .isInvalid();
760 }
761 
762 bool Parser::ParseOpenACCSizeExprList() {
763  if (ParseOpenACCSizeExpr()) {
764  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
766  return false;
767  }
768 
769  while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
770  ExpectAndConsume(tok::comma);
771 
772  if (ParseOpenACCSizeExpr()) {
773  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
775  return false;
776  }
777  }
778  return false;
779 }
780 
781 /// OpenACC 3.3 Section 2.9:
782 ///
783 /// where gang-arg is one of:
784 /// [num:]int-expr
785 /// dim:int-expr
786 /// static:size-expr
787 bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
788 
789  if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) &&
790  NextToken().is(tok::colon)) {
791  // 'static' just takes a size-expr, which is an int-expr or an asterisk.
792  ConsumeToken();
793  ConsumeToken();
794  return ParseOpenACCSizeExpr();
795  }
796 
797  if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) &&
798  NextToken().is(tok::colon)) {
799  ConsumeToken();
800  ConsumeToken();
801  return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
802  OpenACCClauseKind::Gang, GangLoc)
803  .first.isInvalid();
804  }
805 
806  if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) &&
807  NextToken().is(tok::colon)) {
808  ConsumeToken();
809  ConsumeToken();
810  // Fallthrough to the 'int-expr' handling for when 'num' is omitted.
811  }
812  // This is just the 'num' case where 'num' is optional.
813  return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
814  OpenACCClauseKind::Gang, GangLoc)
815  .first.isInvalid();
816 }
817 
818 bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) {
819  if (ParseOpenACCGangArg(GangLoc)) {
820  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
822  return false;
823  }
824 
825  while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
826  ExpectAndConsume(tok::comma);
827 
828  if (ParseOpenACCGangArg(GangLoc)) {
829  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
831  return false;
832  }
833  }
834  return false;
835 }
836 
837 // The OpenACC Clause List is a comma or space-delimited list of clauses (see
838 // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't
839 // really have its owner grammar and each individual one has its own definition.
840 // However, they all are named with a single-identifier (or auto/default!)
841 // token, followed in some cases by either braces or parens.
842 Parser::OpenACCClauseParseResult
843 Parser::ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
844  OpenACCDirectiveKind DirKind) {
845  // A number of clause names are actually keywords, so accept a keyword that
846  // can be converted to a name.
847  if (expectIdentifierOrKeyword(*this))
848  return OpenACCCannotContinue();
849 
850  OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken());
851 
853  Diag(getCurToken(), diag::err_acc_invalid_clause)
854  << getCurToken().getIdentifierInfo();
855  return OpenACCCannotContinue();
856  }
857 
858  // Consume the clause name.
859  SourceLocation ClauseLoc = ConsumeToken();
860 
861  return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);
862 }
863 
864 Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
865  ArrayRef<const OpenACCClause *> ExistingClauses,
866  OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind,
867  SourceLocation ClauseLoc) {
868  BalancedDelimiterTracker Parens(*this, tok::l_paren,
869  tok::annot_pragma_openacc_end);
870  SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc);
871 
872  if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
873  if (Parens.expectAndConsume()) {
874  // We are missing a paren, so assume that the person just forgot the
875  // parameter. Return 'false' so we try to continue on and parse the next
876  // clause.
877  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
879  return OpenACCCanContinue();
880  }
881  ParsedClause.setLParenLoc(Parens.getOpenLocation());
882 
883  switch (ClauseKind) {
885  Token DefKindTok = getCurToken();
886 
887  if (expectIdentifierOrKeyword(*this)) {
888  Parens.skipToEnd();
889  return OpenACCCanContinue();
890  }
891 
892  ConsumeToken();
893 
894  OpenACCDefaultClauseKind DefKind =
895  getOpenACCDefaultClauseKind(DefKindTok);
896 
897  if (DefKind == OpenACCDefaultClauseKind::Invalid) {
898  Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
899  Parens.skipToEnd();
900  return OpenACCCanContinue();
901  }
902 
903  ParsedClause.setDefaultDetails(DefKind);
904  break;
905  }
906  case OpenACCClauseKind::If: {
907  ExprResult CondExpr = ParseOpenACCConditionExpr();
908  ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get()
909  : nullptr);
910 
911  if (CondExpr.isInvalid()) {
912  Parens.skipToEnd();
913  return OpenACCCanContinue();
914  }
915 
916  break;
917  }
921  bool IsReadOnly = tryParseAndConsumeSpecialTokenKind(
922  *this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind);
923  ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind),
924  IsReadOnly,
925  /*IsZero=*/false);
926  break;
927  }
934  bool IsZero = tryParseAndConsumeSpecialTokenKind(
935  *this, OpenACCSpecialTokenKind::Zero, ClauseKind);
936  ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind),
937  /*IsReadOnly=*/false, IsZero);
938  break;
939  }
941  // If we're missing a clause-kind (or it is invalid), see if we can parse
942  // the var-list anyway.
943  OpenACCReductionOperator Op = ParseReductionOperator(*this);
944  ParsedClause.setReductionDetails(Op, ParseOpenACCVarList(ClauseKind));
945  break;
946  }
948  // The 'self' clause is a var-list instead of a 'condition' in the case of
949  // the 'update' clause, so we have to handle it here. U se an assert to
950  // make sure we get the right differentiator.
951  assert(DirKind == OpenACCDirectiveKind::Update);
952  [[fallthrough]];
960  ParseOpenACCVarList(ClauseKind);
961  break;
964  ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind),
965  /*IsReadOnly=*/false, /*IsZero=*/false);
966  break;
974  ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind),
975  /*IsReadOnly=*/false, /*IsZero=*/false);
976  break;
978  tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Force,
979  ClauseKind);
980  ExprResult NumLoops =
981  getActions().CorrectDelayedTyposInExpr(ParseConstantExpression());
982  if (NumLoops.isInvalid()) {
983  Parens.skipToEnd();
984  return OpenACCCanContinue();
985  }
986  break;
987  }
989  ExprResult BindArg = ParseOpenACCBindClauseArgument();
990  if (BindArg.isInvalid()) {
991  Parens.skipToEnd();
992  return OpenACCCanContinue();
993  }
994  break;
995  }
997  llvm::SmallVector<Expr *> IntExprs;
998 
999  if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid,
1000  OpenACCClauseKind::NumGangs, ClauseLoc,
1001  IntExprs)) {
1002  Parens.skipToEnd();
1003  return OpenACCCanContinue();
1004  }
1005  ParsedClause.setIntExprDetails(std::move(IntExprs));
1006  break;
1007  }
1012  ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
1013  ClauseKind, ClauseLoc)
1014  .first;
1015  if (IntExpr.isInvalid()) {
1016  Parens.skipToEnd();
1017  return OpenACCCanContinue();
1018  }
1019 
1020  // TODO OpenACC: as we implement the 'rest' of the above, this 'if' should
1021  // be removed leaving just the 'setIntExprDetails'.
1022  if (ClauseKind == OpenACCClauseKind::NumWorkers ||
1023  ClauseKind == OpenACCClauseKind::VectorLength)
1024  ParsedClause.setIntExprDetails(IntExpr.get());
1025 
1026  break;
1027  }
1031  if (getCurToken().is(tok::star)) {
1032  // FIXME: We want to mark that this is an 'everything else' type of
1033  // device_type in Sema.
1034  ParsedClause.setDeviceTypeDetails({{nullptr, ConsumeToken()}});
1035  } else if (!ParseOpenACCDeviceTypeList(Archs)) {
1036  ParsedClause.setDeviceTypeDetails(std::move(Archs));
1037  } else {
1038  Parens.skipToEnd();
1039  return OpenACCCanContinue();
1040  }
1041  break;
1042  }
1044  if (ParseOpenACCSizeExprList()) {
1045  Parens.skipToEnd();
1046  return OpenACCCanContinue();
1047  }
1048  break;
1049  default:
1050  llvm_unreachable("Not a required parens type?");
1051  }
1052 
1053  ParsedClause.setEndLoc(getCurToken().getLocation());
1054 
1055  if (Parens.consumeClose())
1056  return OpenACCCannotContinue();
1057 
1058  } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
1059  if (!Parens.consumeOpen()) {
1060  ParsedClause.setLParenLoc(Parens.getOpenLocation());
1061  switch (ClauseKind) {
1062  case OpenACCClauseKind::Self: {
1063  assert(DirKind != OpenACCDirectiveKind::Update);
1064  ExprResult CondExpr = ParseOpenACCConditionExpr();
1065  ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get()
1066  : nullptr);
1067 
1068  if (CondExpr.isInvalid()) {
1069  Parens.skipToEnd();
1070  return OpenACCCanContinue();
1071  }
1072  break;
1073  }
1076  tryParseAndConsumeSpecialTokenKind(*this,
1077  ClauseKind ==
1079  ? OpenACCSpecialTokenKind::Length
1080  : OpenACCSpecialTokenKind::Num,
1081  ClauseKind);
1082  ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
1083  ClauseKind, ClauseLoc)
1084  .first;
1085  if (IntExpr.isInvalid()) {
1086  Parens.skipToEnd();
1087  return OpenACCCanContinue();
1088  }
1089  break;
1090  }
1091  case OpenACCClauseKind::Async: {
1092  ExprResult AsyncArg =
1093  ParseOpenACCAsyncArgument(OpenACCDirectiveKind::Invalid,
1094  OpenACCClauseKind::Async, ClauseLoc)
1095  .first;
1096  ParsedClause.setIntExprDetails(AsyncArg.isUsable() ? AsyncArg.get()
1097  : nullptr);
1098  if (AsyncArg.isInvalid()) {
1099  Parens.skipToEnd();
1100  return OpenACCCanContinue();
1101  }
1102  break;
1103  }
1105  if (ParseOpenACCGangArgList(ClauseLoc)) {
1106  Parens.skipToEnd();
1107  return OpenACCCanContinue();
1108  }
1109  break;
1110  case OpenACCClauseKind::Wait: {
1111  OpenACCWaitParseInfo Info =
1112  ParseOpenACCWaitArgument(ClauseLoc,
1113  /*IsDirective=*/false);
1114  if (Info.Failed) {
1115  Parens.skipToEnd();
1116  return OpenACCCanContinue();
1117  }
1118 
1119  ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc,
1120  std::move(Info.QueueIdExprs));
1121  break;
1122  }
1123  default:
1124  llvm_unreachable("Not an optional parens type?");
1125  }
1126  ParsedClause.setEndLoc(getCurToken().getLocation());
1127  if (Parens.consumeClose())
1128  return OpenACCCannotContinue();
1129  } else {
1130  // If we have optional parens, make sure we set the end-location to the
1131  // clause, as we are a 'single token' clause.
1132  ParsedClause.setEndLoc(ClauseLoc);
1133  }
1134  }
1135  return OpenACCSuccess(
1136  Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause));
1137 }
1138 
1139 /// OpenACC 3.3 section 2.16:
1140 /// In this section and throughout the specification, the term async-argument
1141 /// means a nonnegative scalar integer expression (int for C or C++, integer for
1142 /// Fortran), or one of the special values acc_async_noval or acc_async_sync, as
1143 /// defined in the C header file and the Fortran openacc module. The special
1144 /// values are negative values, so as not to conflict with a user-specified
1145 /// nonnegative async-argument.
1146 Parser::OpenACCIntExprParseResult
1147 Parser::ParseOpenACCAsyncArgument(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
1148  SourceLocation Loc) {
1149  return ParseOpenACCIntExpr(DK, CK, Loc);
1150 }
1151 
1152 /// OpenACC 3.3, section 2.16:
1153 /// In this section and throughout the specification, the term wait-argument
1154 /// means:
1155 /// [ devnum : int-expr : ] [ queues : ] async-argument-list
1156 Parser::OpenACCWaitParseInfo
1157 Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
1158  OpenACCWaitParseInfo Result;
1159  // [devnum : int-expr : ]
1160  if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
1161  NextToken().is(tok::colon)) {
1162  // Consume devnum.
1163  ConsumeToken();
1164  // Consume colon.
1165  ConsumeToken();
1166 
1167  OpenACCIntExprParseResult Res = ParseOpenACCIntExpr(
1168  IsDirective ? OpenACCDirectiveKind::Wait
1171  Loc);
1172  if (Res.first.isInvalid() &&
1173  Res.second == OpenACCParseCanContinue::Cannot) {
1174  Result.Failed = true;
1175  return Result;
1176  }
1177 
1178  if (ExpectAndConsume(tok::colon)) {
1179  Result.Failed = true;
1180  return Result;
1181  }
1182 
1183  Result.DevNumExpr = Res.first.get();
1184  }
1185 
1186  // [ queues : ]
1187  if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
1188  NextToken().is(tok::colon)) {
1189  // Consume queues.
1190  Result.QueuesLoc = ConsumeToken();
1191  // Consume colon.
1192  ConsumeToken();
1193  }
1194 
1195  // OpenACC 3.3, section 2.16:
1196  // the term 'async-argument' means a nonnegative scalar integer expression, or
1197  // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined
1198  // in the C header file and the Fortran opacc module.
1199  bool FirstArg = true;
1200  while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1201  if (!FirstArg) {
1202  if (ExpectAndConsume(tok::comma)) {
1203  Result.Failed = true;
1204  return Result;
1205  }
1206  }
1207  FirstArg = false;
1208 
1209  OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1210  IsDirective ? OpenACCDirectiveKind::Wait
1213  Loc);
1214 
1215  if (Res.first.isInvalid() &&
1216  Res.second == OpenACCParseCanContinue::Cannot) {
1217  Result.Failed = true;
1218  return Result;
1219  }
1220 
1221  Result.QueueIdExprs.push_back(Res.first.get());
1222  }
1223 
1224  return Result;
1225 }
1226 
1227 ExprResult Parser::ParseOpenACCIDExpression() {
1228  ExprResult Res;
1229  if (getLangOpts().CPlusPlus) {
1230  Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true);
1231  } else {
1232  // There isn't anything quite the same as ParseCXXIdExpression for C, so we
1233  // need to get the identifier, then call into Sema ourselves.
1234 
1235  if (Tok.isNot(tok::identifier)) {
1236  Diag(Tok, diag::err_expected) << tok::identifier;
1237  return ExprError();
1238  }
1239 
1240  Token FuncName = getCurToken();
1241  UnqualifiedId Name;
1242  CXXScopeSpec ScopeSpec;
1243  SourceLocation TemplateKWLoc;
1244  Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken());
1245 
1246  // Ensure this is a valid identifier. We don't accept causing implicit
1247  // function declarations per the spec, so always claim to not have trailing
1248  // L Paren.
1249  Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
1250  Name, /*HasTrailingLParen=*/false,
1251  /*isAddressOfOperand=*/false);
1252  }
1253 
1254  return getActions().CorrectDelayedTyposInExpr(Res);
1255 }
1256 
1257 ExprResult Parser::ParseOpenACCBindClauseArgument() {
1258  // OpenACC 3.3 section 2.15:
1259  // The bind clause specifies the name to use when calling the procedure on a
1260  // device other than the host. If the name is specified as an identifier, it
1261  // is called as if that name were specified in the language being compiled. If
1262  // the name is specified as a string, the string is used for the procedure
1263  // name unmodified.
1264  if (getCurToken().is(tok::r_paren)) {
1265  Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
1266  return ExprError();
1267  }
1268 
1269  if (tok::isStringLiteral(getCurToken().getKind()))
1270  return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression(
1271  /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
1272 
1273  return ParseOpenACCIDExpression();
1274 }
1275 
1276 /// OpenACC 3.3, section 1.6:
1277 /// In this spec, a 'var' (in italics) is one of the following:
1278 /// - a variable name (a scalar, array, or composite variable name)
1279 /// - a subarray specification with subscript ranges
1280 /// - an array element
1281 /// - a member of a composite variable
1282 /// - a common block name between slashes (fortran only)
1283 Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCClauseKind CK) {
1284  OpenACCArraySectionRAII ArraySections(*this);
1285 
1286  ExprResult Res = ParseAssignmentExpression();
1287  if (!Res.isUsable())
1288  return {Res, OpenACCParseCanContinue::Cannot};
1289 
1290  Res = getActions().CorrectDelayedTyposInExpr(Res.get());
1291  if (!Res.isUsable())
1292  return {Res, OpenACCParseCanContinue::Can};
1293 
1294  Res = getActions().OpenACC().ActOnVar(CK, Res.get());
1295 
1296  return {Res, OpenACCParseCanContinue::Can};
1297 }
1298 
1299 llvm::SmallVector<Expr *> Parser::ParseOpenACCVarList(OpenACCClauseKind CK) {
1301 
1302  auto [Res, CanContinue] = ParseOpenACCVar(CK);
1303  if (Res.isUsable()) {
1304  Vars.push_back(Res.get());
1305  } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1306  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch);
1307  return Vars;
1308  }
1309 
1310  while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1311  ExpectAndConsume(tok::comma);
1312 
1313  auto [Res, CanContinue] = ParseOpenACCVar(CK);
1314 
1315  if (Res.isUsable()) {
1316  Vars.push_back(Res.get());
1317  } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1318  SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch);
1319  return Vars;
1320  }
1321  }
1322  return Vars;
1323 }
1324 
1325 /// OpenACC 3.3, section 2.10:
1326 /// In C and C++, the syntax of the cache directive is:
1327 ///
1328 /// #pragma acc cache ([readonly:]var-list) new-line
1329 void Parser::ParseOpenACCCacheVarList() {
1330  // If this is the end of the line, just return 'false' and count on the close
1331  // paren diagnostic to catch the issue.
1332  if (getCurToken().isAnnotation())
1333  return;
1334 
1335  // The VarList is an optional `readonly:` followed by a list of a variable
1336  // specifications. Consume something that looks like a 'tag', and diagnose if
1337  // it isn't 'readonly'.
1338  if (tryParseAndConsumeSpecialTokenKind(*this,
1339  OpenACCSpecialTokenKind::ReadOnly,
1341  // FIXME: Record that this is a 'readonly' so that we can use that during
1342  // Sema/AST generation.
1343  }
1344 
1345  // ParseOpenACCVarList should leave us before a r-paren, so no need to skip
1346  // anything here.
1347  ParseOpenACCVarList(OpenACCClauseKind::Invalid);
1348 }
1349 
1350 Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
1351  SourceLocation StartLoc = getCurToken().getLocation();
1352  OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);
1353 
1354  getActions().OpenACC().ActOnConstruct(DirKind, StartLoc);
1355 
1356  // Once we've parsed the construct/directive name, some have additional
1357  // specifiers that need to be taken care of. Atomic has an 'atomic-clause'
1358  // that needs to be parsed.
1359  if (DirKind == OpenACCDirectiveKind::Atomic)
1360  ParseOpenACCAtomicKind(*this);
1361 
1362  // We've successfully parsed the construct/directive name, however a few of
1363  // the constructs have optional parens that contain further details.
1364  BalancedDelimiterTracker T(*this, tok::l_paren,
1365  tok::annot_pragma_openacc_end);
1366 
1367  if (!T.consumeOpen()) {
1368  switch (DirKind) {
1369  default:
1370  Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren);
1371  T.skipToEnd();
1372  break;
1374  // Routine has an optional paren-wrapped name of a function in the local
1375  // scope. We parse the name, emitting any diagnostics
1376  ExprResult RoutineName = ParseOpenACCIDExpression();
1377  // If the routine name is invalid, just skip until the closing paren to
1378  // recover more gracefully.
1379  if (RoutineName.isInvalid())
1380  T.skipToEnd();
1381  else
1382  T.consumeClose();
1383  break;
1384  }
1386  ParseOpenACCCacheVarList();
1387  // The ParseOpenACCCacheVarList function manages to recover from failures,
1388  // so we can always consume the close.
1389  T.consumeClose();
1390  break;
1392  // OpenACC has an optional paren-wrapped 'wait-argument'.
1393  if (ParseOpenACCWaitArgument(StartLoc, /*IsDirective=*/true).Failed)
1394  T.skipToEnd();
1395  else
1396  T.consumeClose();
1397  break;
1398  }
1399  } else if (DirKind == OpenACCDirectiveKind::Cache) {
1400  // Cache's paren var-list is required, so error here if it isn't provided.
1401  // We know that the consumeOpen above left the first non-paren here, so
1402  // diagnose, then continue as if it was completely omitted.
1403  Diag(Tok, diag::err_expected) << tok::l_paren;
1404  }
1405 
1406  // Parses the list of clauses, if present, plus set up return value.
1407  OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, SourceLocation{},
1408  ParseOpenACCClauseList(DirKind)};
1409 
1410  assert(Tok.is(tok::annot_pragma_openacc_end) &&
1411  "Didn't parse all OpenACC Clauses");
1412  ParseInfo.EndLoc = ConsumeAnnotationToken();
1413  assert(ParseInfo.EndLoc.isValid() &&
1414  "Terminating annotation token not present");
1415 
1416  return ParseInfo;
1417 }
1418 
1419 // Parse OpenACC directive on a declaration.
1421  assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1422 
1423  ParsingOpenACCDirectiveRAII DirScope(*this);
1424  ConsumeAnnotationToken();
1425 
1426  OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1427 
1428  if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind,
1429  DirInfo.StartLoc))
1430  return nullptr;
1431 
1432  // TODO OpenACC: Do whatever decl parsing is required here.
1433  return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective());
1434 }
1435 
1436 // Parse OpenACC Directive on a Statement.
1438  assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1439 
1440  ParsingOpenACCDirectiveRAII DirScope(*this);
1441  ConsumeAnnotationToken();
1442 
1443  OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1444  if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind,
1445  DirInfo.StartLoc))
1446  return StmtError();
1447 
1448  StmtResult AssocStmt;
1449 
1450  if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {
1451  ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
1452  ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind));
1453 
1454  AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(DirInfo.DirKind,
1455  ParseStatement());
1456  }
1457 
1458  return getActions().OpenACC().ActOnEndStmtDirective(
1459  DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, DirInfo.Clauses,
1460  AssocStmt);
1461 }
StringRef P
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:1125
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Defines some OpenACC-specific enums and functions.
constexpr static bool isOneOf()
SourceLocation Loc
Definition: SemaObjC.cpp:755
This file declares semantic analysis for OpenACC constructs and clauses.
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
One of these records is kept for each identifier that is lexed.
bool isKeyword(const LangOptions &LangOpts) const
Return true if this token is a keyword in the specified language.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
Wrapper for void* pointer.
Definition: Ownership.h:50
This is the base type for all OpenACC Clauses.
Definition: OpenACCClause.h:24
ParseScope - Introduces a new scope for parsing.
Definition: Parser.h:1168
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:58
DeclGroupPtrTy ParseOpenACCDirectiveDecl()
Placeholder for now, should just ignore the directives after emitting a diagnostic.
StmtResult ParseOpenACCDirectiveStmt()
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
Definition: Parser.h:1272
Activates OpenACC parsing mode to preseve OpenACC specific annotation tokens.
@ ContinueScope
This is a while, do, for, which can have continue statements embedded into it.
Definition: Scope.h:59
@ OpenACCComputeConstructScope
This is the scope of an OpenACC Compute Construct, which restricts jumping into/out of it.
Definition: Scope.h:158
@ BreakScope
This is a while, do, switch, for, etc that can have break statements embedded into it.
Definition: Scope.h:55
A type to represent all the data for an OpenACC Clause that has been parsed, but not yet created/sema...
Definition: SemaOpenACC.h:36
void setLParenLoc(SourceLocation EndLoc)
Definition: SemaOpenACC.h:240
void setConditionDetails(Expr *ConditionExpr)
Definition: SemaOpenACC.h:249
void setReductionDetails(OpenACCReductionOperator Op, llvm::SmallVector< Expr * > &&VarList)
Definition: SemaOpenACC.h:351
void setDefaultDetails(OpenACCDefaultClauseKind DefKind)
Definition: SemaOpenACC.h:243
void setVarListDetails(ArrayRef< Expr * > VarList, bool IsReadOnly, bool IsZero)
Definition: SemaOpenACC.h:280
void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc, llvm::SmallVector< Expr * > &&IntExprs)
Definition: SemaOpenACC.h:358
void setEndLoc(SourceLocation EndLoc)
Definition: SemaOpenACC.h:241
void setIntExprDetails(ArrayRef< Expr * > IntExprs)
Definition: SemaOpenACC.h:263
void setDeviceTypeDetails(llvm::SmallVector< DeviceTypeArgument > &&Archs)
Definition: SemaOpenACC.h:365
bool isInvalid() const
Definition: Sema.h:6006
@ Boolean
A boolean condition, from 'if', 'while', 'for', or 'do'.
Encodes a location in the source.
Token - This structure provides full information about a lexed token.
Definition: Token.h:36
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition: Token.h:99
tok::TokenKind getKind() const
Definition: Token.h:94
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:187
bool isNot(tok::TokenKind K) const
Definition: Token.h:100
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Definition: Token.h:121
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:1025
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
bool Zero(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1877
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
Definition: TokenKinds.h:89
bool isAnnotation(TokenKind K)
Return true if this is any of tok::annot_* kinds.
Definition: TokenKinds.cpp:58
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCClauseKind
Represents the kind of an OpenACC clause.
Definition: OpenACCKinds.h:164
@ Auto
'auto' clause, allowed on 'loop' directives.
@ Bind
'bind' clause, allowed on routine constructs.
@ Gang
'gang' clause, allowed on 'loop' and Combined constructs.
@ Wait
'wait' clause, allowed on Compute, Data, 'update', and Combined constructs.
@ DevicePtr
'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ PCopyOut
'copyout' clause alias 'pcopyout'. Preserved for diagnostic purposes.
@ VectorLength
'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop', and 'kernels loop' constru...
@ Async
'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined constructs.
@ PresentOrCreate
'create' clause alias 'present_or_create'.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ NoHost
'nohost' clause, allowed on 'routine' directives.
@ PresentOrCopy
'copy' clause alias 'present_or_copy'. Preserved for diagnostic purposes.
@ DeviceNum
'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Invalid
Represents an invalid clause, for the purposes of parsing.
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Copy
'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ DeviceType
'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown', 'set', update',...
@ DefaultAsync
'default_async' clause, allowed on 'set' construct.
@ Attach
'attach' clause, allowed on Compute and Combined constructs, plus 'data' and 'enter data'.
@ NumGangs
'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Default
'default' clause, allowed on parallel, serial, kernel (and compound) constructs.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ NoCreate
'no_create' clause, allowed on allowed on Compute and Combined constructs, plus 'data'.
@ PresentOrCopyOut
'copyout' clause alias 'present_or_copyout'.
@ Link
'link' clause, allowed on 'declare' construct.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
@ CopyOut
'copyout' clause, allowed on Compute and Combined constructs, plus 'data', 'exit data',...
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
@ FirstPrivate
'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', and 'serial loop' constructs...
@ Host
'host' clause, allowed on 'update' construct.
@ PCopy
'copy' clause alias 'pcopy'. Preserved for diagnostic purposes.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ PCopyIn
'copyin' clause alias 'pcopyin'. Preserved for diagnostic purposes.
@ DeviceResident
'device_resident' clause, allowed on the 'declare' construct.
@ PCreate
'create' clause alias 'pcreate'. Preserved for diagnostic purposes.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
@ DType
'dtype' clause, an alias for 'device_type', stored separately for diagnostic purposes.
@ CopyIn
'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ Device
'device' clause, allowed on the 'update' construct.
@ Independent
'independent' clause, allowed on 'loop' directives.
@ NumWorkers
'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs...
@ IfPresent
'if_present' clause, allowed on 'host_data' and 'update' directives.
@ Detach
'detach' clause, allowed on the 'exit data' construct.
@ Delete
'delete' clause, allowed on the 'exit data' construct.
@ PresentOrCopyIn
'copyin' clause alias 'present_or_copyin'.
@ Finalize
'finalize' clause, allowed on 'exit data' directive.
@ CPlusPlus
Definition: LangStandard.h:55
OpenACCAtomicKind
Definition: OpenACCKinds.h:155
StmtResult StmtError()
Definition: Ownership.h:265
OpenACCDefaultClauseKind
Definition: OpenACCKinds.h:462
@ Invalid
Not a valid option.
OpenACCDirectiveKind
Definition: OpenACCKinds.h:25
ExprResult ExprError()
Definition: Ownership.h:264
const FunctionProtoType * T
OpenACCReductionOperator
Definition: OpenACCKinds.h:495
@ Invalid
Invalid Reduction Clause Kind.
@ Parens
New-expression has a C++98 paren-delimited initializer.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30