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
22using namespace clang;
23using namespace llvm;
24
25namespace {
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.
29enum 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`.
41OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {
42 if (!Tok.is(K: tok::identifier))
43 return OpenACCDirectiveKindEx::Invalid;
44 OpenACCDirectiveKind DirKind =
45 llvm::StringSwitch<OpenACCDirectiveKind>(
46 Tok.getIdentifierInfo()->getName())
47 .Case(S: "parallel", Value: OpenACCDirectiveKind::Parallel)
48 .Case(S: "serial", Value: OpenACCDirectiveKind::Serial)
49 .Case(S: "kernels", Value: OpenACCDirectiveKind::Kernels)
50 .Case(S: "data", Value: OpenACCDirectiveKind::Data)
51 .Case(S: "host_data", Value: OpenACCDirectiveKind::HostData)
52 .Case(S: "loop", Value: OpenACCDirectiveKind::Loop)
53 .Case(S: "cache", Value: OpenACCDirectiveKind::Cache)
54 .Case(S: "atomic", Value: OpenACCDirectiveKind::Atomic)
55 .Case(S: "routine", Value: OpenACCDirectiveKind::Routine)
56 .Case(S: "declare", Value: OpenACCDirectiveKind::Declare)
57 .Case(S: "init", Value: OpenACCDirectiveKind::Init)
58 .Case(S: "shutdown", Value: OpenACCDirectiveKind::Shutdown)
59 .Case(S: "set", Value: OpenACCDirectiveKind::Set)
60 .Case(S: "update", Value: OpenACCDirectiveKind::Update)
61 .Case(S: "wait", Value: OpenACCDirectiveKind::Wait)
62 .Default(Value: 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(S: "enter", Value: OpenACCDirectiveKindEx::Enter)
70 .Case(S: "exit", Value: OpenACCDirectiveKindEx::Exit)
71 .Default(Value: OpenACCDirectiveKindEx::Invalid);
72}
73
74// Translate single-token string representations to the OpenCC Clause Kind.
75OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
76 // auto is a keyword in some language modes, so make sure we parse it
77 // correctly.
78 if (Tok.is(K: tok::kw_auto))
79 return OpenACCClauseKind::Auto;
80
81 // default is a keyword, so make sure we parse it correctly.
82 if (Tok.is(K: tok::kw_default))
83 return OpenACCClauseKind::Default;
84
85 // if is also a keyword, make sure we parse it correctly.
86 if (Tok.is(K: tok::kw_if))
87 return OpenACCClauseKind::If;
88
89 // 'private' is also a keyword, make sure we pare it correctly.
90 if (Tok.is(K: tok::kw_private))
91 return OpenACCClauseKind::Private;
92
93 if (!Tok.is(K: tok::identifier))
94 return OpenACCClauseKind::Invalid;
95
96 return llvm::StringSwitch<OpenACCClauseKind>(
97 Tok.getIdentifierInfo()->getName())
98 .Case(S: "async", Value: OpenACCClauseKind::Async)
99 .Case(S: "attach", Value: OpenACCClauseKind::Attach)
100 .Case(S: "auto", Value: OpenACCClauseKind::Auto)
101 .Case(S: "bind", Value: OpenACCClauseKind::Bind)
102 .Case(S: "create", Value: OpenACCClauseKind::Create)
103 .Case(S: "pcreate", Value: OpenACCClauseKind::PCreate)
104 .Case(S: "present_or_create", Value: OpenACCClauseKind::PresentOrCreate)
105 .Case(S: "collapse", Value: OpenACCClauseKind::Collapse)
106 .Case(S: "copy", Value: OpenACCClauseKind::Copy)
107 .Case(S: "pcopy", Value: OpenACCClauseKind::PCopy)
108 .Case(S: "present_or_copy", Value: OpenACCClauseKind::PresentOrCopy)
109 .Case(S: "copyin", Value: OpenACCClauseKind::CopyIn)
110 .Case(S: "pcopyin", Value: OpenACCClauseKind::PCopyIn)
111 .Case(S: "present_or_copyin", Value: OpenACCClauseKind::PresentOrCopyIn)
112 .Case(S: "copyout", Value: OpenACCClauseKind::CopyOut)
113 .Case(S: "pcopyout", Value: OpenACCClauseKind::PCopyOut)
114 .Case(S: "present_or_copyout", Value: OpenACCClauseKind::PresentOrCopyOut)
115 .Case(S: "default", Value: OpenACCClauseKind::Default)
116 .Case(S: "default_async", Value: OpenACCClauseKind::DefaultAsync)
117 .Case(S: "delete", Value: OpenACCClauseKind::Delete)
118 .Case(S: "detach", Value: OpenACCClauseKind::Detach)
119 .Case(S: "device", Value: OpenACCClauseKind::Device)
120 .Case(S: "device_num", Value: OpenACCClauseKind::DeviceNum)
121 .Case(S: "device_resident", Value: OpenACCClauseKind::DeviceResident)
122 .Case(S: "device_type", Value: OpenACCClauseKind::DeviceType)
123 .Case(S: "deviceptr", Value: OpenACCClauseKind::DevicePtr)
124 .Case(S: "dtype", Value: OpenACCClauseKind::DType)
125 .Case(S: "finalize", Value: OpenACCClauseKind::Finalize)
126 .Case(S: "firstprivate", Value: OpenACCClauseKind::FirstPrivate)
127 .Case(S: "gang", Value: OpenACCClauseKind::Gang)
128 .Case(S: "host", Value: OpenACCClauseKind::Host)
129 .Case(S: "if", Value: OpenACCClauseKind::If)
130 .Case(S: "if_present", Value: OpenACCClauseKind::IfPresent)
131 .Case(S: "independent", Value: OpenACCClauseKind::Independent)
132 .Case(S: "link", Value: OpenACCClauseKind::Link)
133 .Case(S: "no_create", Value: OpenACCClauseKind::NoCreate)
134 .Case(S: "num_gangs", Value: OpenACCClauseKind::NumGangs)
135 .Case(S: "num_workers", Value: OpenACCClauseKind::NumWorkers)
136 .Case(S: "nohost", Value: OpenACCClauseKind::NoHost)
137 .Case(S: "present", Value: OpenACCClauseKind::Present)
138 .Case(S: "private", Value: OpenACCClauseKind::Private)
139 .Case(S: "reduction", Value: OpenACCClauseKind::Reduction)
140 .Case(S: "self", Value: OpenACCClauseKind::Self)
141 .Case(S: "seq", Value: OpenACCClauseKind::Seq)
142 .Case(S: "tile", Value: OpenACCClauseKind::Tile)
143 .Case(S: "use_device", Value: OpenACCClauseKind::UseDevice)
144 .Case(S: "vector", Value: OpenACCClauseKind::Vector)
145 .Case(S: "vector_length", Value: OpenACCClauseKind::VectorLength)
146 .Case(S: "wait", Value: OpenACCClauseKind::Wait)
147 .Case(S: "worker", Value: OpenACCClauseKind::Worker)
148 .Default(Value: OpenACCClauseKind::Invalid);
149}
150
151// Since 'atomic' is effectively a compound directive, this will decode the
152// second part of the directive.
153OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
154 if (!Tok.is(K: tok::identifier))
155 return OpenACCAtomicKind::Invalid;
156 return llvm::StringSwitch<OpenACCAtomicKind>(
157 Tok.getIdentifierInfo()->getName())
158 .Case(S: "read", Value: OpenACCAtomicKind::Read)
159 .Case(S: "write", Value: OpenACCAtomicKind::Write)
160 .Case(S: "update", Value: OpenACCAtomicKind::Update)
161 .Case(S: "capture", Value: OpenACCAtomicKind::Capture)
162 .Default(Value: OpenACCAtomicKind::Invalid);
163}
164
165OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) {
166 if (!Tok.is(K: tok::identifier))
167 return OpenACCDefaultClauseKind::Invalid;
168
169 return llvm::StringSwitch<OpenACCDefaultClauseKind>(
170 Tok.getIdentifierInfo()->getName())
171 .Case(S: "none", Value: OpenACCDefaultClauseKind::None)
172 .Case(S: "present", Value: OpenACCDefaultClauseKind::Present)
173 .Default(Value: OpenACCDefaultClauseKind::Invalid);
174}
175
176enum class OpenACCSpecialTokenKind {
177 ReadOnly,
178 DevNum,
179 Queues,
180 Zero,
181 Force,
182 Num,
183 Length,
184 Dim,
185 Static,
186};
187
188bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {
189 if (Tok.is(K: tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static)
190 return true;
191
192 if (!Tok.is(K: tok::identifier))
193 return false;
194
195 switch (Kind) {
196 case OpenACCSpecialTokenKind::ReadOnly:
197 return Tok.getIdentifierInfo()->isStr(Str: "readonly");
198 case OpenACCSpecialTokenKind::DevNum:
199 return Tok.getIdentifierInfo()->isStr(Str: "devnum");
200 case OpenACCSpecialTokenKind::Queues:
201 return Tok.getIdentifierInfo()->isStr(Str: "queues");
202 case OpenACCSpecialTokenKind::Zero:
203 return Tok.getIdentifierInfo()->isStr(Str: "zero");
204 case OpenACCSpecialTokenKind::Force:
205 return Tok.getIdentifierInfo()->isStr(Str: "force");
206 case OpenACCSpecialTokenKind::Num:
207 return Tok.getIdentifierInfo()->isStr(Str: "num");
208 case OpenACCSpecialTokenKind::Length:
209 return Tok.getIdentifierInfo()->isStr(Str: "length");
210 case OpenACCSpecialTokenKind::Dim:
211 return Tok.getIdentifierInfo()->isStr(Str: "dim");
212 case OpenACCSpecialTokenKind::Static:
213 return Tok.getIdentifierInfo()->isStr(Str: "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.
221bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) {
222 if (Tok.is(K: tok::identifier))
223 return true;
224
225 if (!Tok.isAnnotation() && Tok.getIdentifierInfo() &&
226 Tok.getIdentifierInfo()->isKeyword(LangOpts: 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.
237template <typename DirOrClauseTy>
238bool 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, Tok: IdentTok) && P.NextToken().is(K: tok::colon)) {
244 P.ConsumeToken();
245 P.ConsumeToken();
246
247 if (!isOpenACCSpecialToken(Kind, Tok: IdentTok)) {
248 P.Diag(Tok: IdentTok, DiagID: 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
260bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
261 if (!Tok.is(K: tok::identifier))
262 return false;
263
264 switch (Kind) {
265 case OpenACCDirectiveKind::Parallel:
266 return Tok.getIdentifierInfo()->isStr(Str: "parallel");
267 case OpenACCDirectiveKind::Serial:
268 return Tok.getIdentifierInfo()->isStr(Str: "serial");
269 case OpenACCDirectiveKind::Kernels:
270 return Tok.getIdentifierInfo()->isStr(Str: "kernels");
271 case OpenACCDirectiveKind::Data:
272 return Tok.getIdentifierInfo()->isStr(Str: "data");
273 case OpenACCDirectiveKind::HostData:
274 return Tok.getIdentifierInfo()->isStr(Str: "host_data");
275 case OpenACCDirectiveKind::Loop:
276 return Tok.getIdentifierInfo()->isStr(Str: "loop");
277 case OpenACCDirectiveKind::Cache:
278 return Tok.getIdentifierInfo()->isStr(Str: "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(Str: "atomic");
289 case OpenACCDirectiveKind::Routine:
290 return Tok.getIdentifierInfo()->isStr(Str: "routine");
291 case OpenACCDirectiveKind::Declare:
292 return Tok.getIdentifierInfo()->isStr(Str: "declare");
293 case OpenACCDirectiveKind::Init:
294 return Tok.getIdentifierInfo()->isStr(Str: "init");
295 case OpenACCDirectiveKind::Shutdown:
296 return Tok.getIdentifierInfo()->isStr(Str: "shutdown");
297 case OpenACCDirectiveKind::Set:
298 return Tok.getIdentifierInfo()->isStr(Str: "set");
299 case OpenACCDirectiveKind::Update:
300 return Tok.getIdentifierInfo()->isStr(Str: "update");
301 case OpenACCDirectiveKind::Wait:
302 return Tok.getIdentifierInfo()->isStr(Str: "wait");
303 case OpenACCDirectiveKind::Invalid:
304 return false;
305 }
306 llvm_unreachable("Unknown 'Kind' Passed");
307}
308
309OpenACCReductionOperator 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(K: tok::colon)) {
314 P.Diag(Tok: P.getCurToken(), DiagID: 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(Str: "max"))
339 return OpenACCReductionOperator::Max;
340 if (ReductionKindTok.getIdentifierInfo()->isStr(Str: "min"))
341 return OpenACCReductionOperator::Min;
342 [[fallthrough]];
343 default:
344 P.Diag(Tok: ReductionKindTok, DiagID: 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.
352bool expectIdentifierOrKeyword(Parser &P) {
353 Token Tok = P.getCurToken();
354
355 if (isTokenIdentifierOrKeyword(P, Tok))
356 return false;
357
358 P.Diag(Tok: P.getCurToken(), DiagID: diag::err_expected) << tok::identifier;
359 return true;
360}
361
362OpenACCDirectiveKind
363ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
364 OpenACCDirectiveKindEx ExtDirKind) {
365 Token SecondTok = P.getCurToken();
366
367 if (SecondTok.isAnnotation()) {
368 P.Diag(Tok: FirstTok, DiagID: 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(Kind: OpenACCDirectiveKind::Data, Tok: SecondTok)) {
378 if (!SecondTok.is(K: tok::identifier))
379 P.Diag(Tok: SecondTok, DiagID: diag::err_expected) << tok::identifier;
380 else
381 P.Diag(Tok: FirstTok, DiagID: 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
392OpenACCAtomicKind 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(Tok: 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.
412OpenACCDirectiveKind 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(K: tok::identifier)) {
418 P.Diag(Tok: FirstTok, DiagID: diag::err_acc_missing_directive);
419
420 if (P.getCurToken().isNot(K: tok::annot_pragma_openacc_end))
421 P.ConsumeAnyToken();
422
423 return OpenACCDirectiveKind::Invalid;
424 }
425
426 P.ConsumeToken();
427
428 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(Tok: 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(Tok: FirstTok, DiagID: 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, ExtDirKind: 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(Kind: OpenACCDirectiveKind::Loop, Tok: 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
477enum ClauseParensKind {
478 None,
479 Optional,
480 Required
481};
482
483ClauseParensKind 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
548bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind,
549 OpenACCClauseKind Kind) {
550 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
551}
552
553bool 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.
562void SkipUntilEndOfDirective(Parser &P) {
563 while (P.getCurToken().isNot(K: tok::annot_pragma_openacc_end))
564 P.ConsumeAnyToken();
565}
566
567bool 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
580unsigned 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
599Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
600 return {nullptr, OpenACCParseCanContinue::Can};
601}
602
603Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
604 return {nullptr, OpenACCParseCanContinue::Cannot};
605}
606
607Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {
608 return {Clause, OpenACCParseCanContinue::Can};
609}
610
611ExprResult 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(ER: ParseExpression());
617
618 if (!ER.isUsable())
619 return ER;
620
621 Sema::ConditionResult R =
622 getActions().ActOnCondition(S: getCurScope(), Loc: ER.get()->getExprLoc(),
623 SubExpr: ER.get(), CK: 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.
633SmallVector<OpenACCClause *>
634Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
635 SmallVector<OpenACCClause *> Clauses;
636 bool FirstClause = true;
637 while (getCurToken().isNot(K: tok::annot_pragma_openacc_end)) {
638 // Comma is optional in a clause-list.
639 if (!FirstClause && getCurToken().is(K: tok::comma))
640 ConsumeToken();
641 FirstClause = false;
642
643 OpenACCClauseParseResult Result = ParseOpenACCClause(ExistingClauses: Clauses, DirKind);
644 if (OpenACCClause *Clause = Result.getPointer()) {
645 Clauses.push_back(Elt: 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(P&: *this);
650 return Clauses;
651 }
652 }
653 return Clauses;
654}
655
656Parser::OpenACCIntExprParseResult
657Parser::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, IntExpr: ER.get()),
673 OpenACCParseCanContinue::Can};
674}
675
676bool 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(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
684 Flags: Parser::StopBeforeMatch);
685 return true;
686 }
687
688 IntExprs.push_back(Elt: CurResult.first.get());
689
690 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
691 ExpectAndConsume(ExpectedTok: tok::comma);
692
693 CurResult = ParseOpenACCIntExpr(DK, CK, Loc);
694
695 if (!CurResult.first.isUsable() &&
696 CurResult.second == OpenACCParseCanContinue::Cannot) {
697 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
698 Flags: Parser::StopBeforeMatch);
699 return true;
700 }
701 IntExprs.push_back(Elt: 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.
715bool Parser::ParseOpenACCDeviceTypeList(
716 llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs) {
717
718 if (expectIdentifierOrKeyword(P&: *this)) {
719 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
720 Flags: Parser::StopBeforeMatch);
721 return true;
722 }
723 IdentifierInfo *Ident = getCurToken().getIdentifierInfo();
724 Archs.emplace_back(Args&: Ident, Args: ConsumeToken());
725
726 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
727 ExpectAndConsume(ExpectedTok: tok::comma);
728
729 if (expectIdentifierOrKeyword(P&: *this)) {
730 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
731 Flags: Parser::StopBeforeMatch);
732 return true;
733 }
734 Ident = getCurToken().getIdentifierInfo();
735 Archs.emplace_back(Args&: Ident, Args: 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.
746bool 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(K: tok::star) &&
752 NextToken().isOneOf(K1: tok::comma, Ks: tok::r_paren,
753 Ks: tok::annot_pragma_openacc_end)) {
754 ConsumeToken();
755 return false;
756 }
757
758 return getActions()
759 .CorrectDelayedTyposInExpr(ER: ParseAssignmentExpression())
760 .isInvalid();
761}
762
763bool Parser::ParseOpenACCSizeExprList() {
764 if (ParseOpenACCSizeExpr()) {
765 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
766 Flags: Parser::StopBeforeMatch);
767 return false;
768 }
769
770 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
771 ExpectAndConsume(ExpectedTok: tok::comma);
772
773 if (ParseOpenACCSizeExpr()) {
774 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
775 Flags: 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
788bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
789
790 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::Static, Tok: getCurToken()) &&
791 NextToken().is(K: 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(Kind: OpenACCSpecialTokenKind::Dim, Tok: getCurToken()) &&
799 NextToken().is(K: tok::colon)) {
800 ConsumeToken();
801 ConsumeToken();
802 return ParseOpenACCIntExpr(DK: OpenACCDirectiveKind::Invalid,
803 CK: OpenACCClauseKind::Gang, Loc: GangLoc)
804 .first.isInvalid();
805 }
806
807 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::Num, Tok: getCurToken()) &&
808 NextToken().is(K: 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(DK: OpenACCDirectiveKind::Invalid,
815 CK: OpenACCClauseKind::Gang, Loc: GangLoc)
816 .first.isInvalid();
817}
818
819bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) {
820 if (ParseOpenACCGangArg(GangLoc)) {
821 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
822 Flags: Parser::StopBeforeMatch);
823 return false;
824 }
825
826 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
827 ExpectAndConsume(ExpectedTok: tok::comma);
828
829 if (ParseOpenACCGangArg(GangLoc)) {
830 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
831 Flags: 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.
843Parser::OpenACCClauseParseResult
844Parser::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(P&: *this))
849 return OpenACCCannotContinue();
850
851 OpenACCClauseKind Kind = getOpenACCClauseKind(Tok: getCurToken());
852
853 if (Kind == OpenACCClauseKind::Invalid) {
854 Diag(Tok: getCurToken(), DiagID: 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
865Parser::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, Kind: 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(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openacc_end,
879 Flags: 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(P&: *this)) {
889 Parens.skipToEnd();
890 return OpenACCCanContinue();
891 }
892
893 ConsumeToken();
894
895 OpenACCDefaultClauseKind DefKind =
896 getOpenACCDefaultClauseKind(Tok: DefKindTok);
897
898 if (DefKind == OpenACCDefaultClauseKind::Invalid) {
899 Diag(Tok: DefKindTok, DiagID: 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 P&: *this, Kind: OpenACCSpecialTokenKind::ReadOnly, DirOrClause: ClauseKind);
924 ParsedClause.setVarListDetails(VarList: ParseOpenACCVarList(CK: 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 P&: *this, Kind: OpenACCSpecialTokenKind::Zero, DirOrClause: ClauseKind);
937 ParsedClause.setVarListDetails(VarList: ParseOpenACCVarList(CK: 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(P&: *this);
945 ParsedClause.setReductionDetails(Op, VarList: ParseOpenACCVarList(CK: 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(CK: ClauseKind);
962 break;
963 case OpenACCClauseKind::Attach:
964 case OpenACCClauseKind::DevicePtr:
965 ParsedClause.setVarListDetails(VarList: ParseOpenACCVarList(CK: 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(VarList: ParseOpenACCVarList(CK: ClauseKind),
976 /*IsReadOnly=*/false, /*IsZero=*/false);
977 break;
978 case OpenACCClauseKind::Collapse: {
979 tryParseAndConsumeSpecialTokenKind(P&: *this, Kind: OpenACCSpecialTokenKind::Force,
980 DirOrClause: ClauseKind);
981 ExprResult NumLoops =
982 getActions().CorrectDelayedTyposInExpr(ER: 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(DK: OpenACCDirectiveKind::Invalid,
1001 CK: OpenACCClauseKind::NumGangs, Loc: 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(DK: OpenACCDirectiveKind::Invalid,
1014 CK: ClauseKind, Loc: 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(K: 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, Kind: 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(P&: *this,
1078 Kind: ClauseKind ==
1079 OpenACCClauseKind::Vector
1080 ? OpenACCSpecialTokenKind::Length
1081 : OpenACCSpecialTokenKind::Num,
1082 DirOrClause: ClauseKind);
1083 ExprResult IntExpr = ParseOpenACCIntExpr(DK: OpenACCDirectiveKind::Invalid,
1084 CK: ClauseKind, Loc: 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(DK: OpenACCDirectiveKind::Invalid,
1095 CK: OpenACCClauseKind::Async, Loc: 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(GangLoc: ClauseLoc)) {
1107 Parens.skipToEnd();
1108 return OpenACCCanContinue();
1109 }
1110 break;
1111 case OpenACCClauseKind::Wait: {
1112 OpenACCWaitParseInfo Info =
1113 ParseOpenACCWaitArgument(Loc: ClauseLoc,
1114 /*IsDirective=*/false);
1115 if (Info.Failed) {
1116 Parens.skipToEnd();
1117 return OpenACCCanContinue();
1118 }
1119
1120 ParsedClause.setWaitDetails(DevNum: Info.DevNumExpr, QueuesLoc: Info.QueuesLoc,
1121 IntExprs: 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 Clause: Actions.OpenACC().ActOnClause(ExistingClauses, Clause&: 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.
1149Parser::OpenACCIntExprParseResult
1150Parser::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
1159Parser::OpenACCWaitParseInfo
1160Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
1161 OpenACCWaitParseInfo Result;
1162 // [devnum : int-expr : ]
1163 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::DevNum, Tok) &&
1164 NextToken().is(K: tok::colon)) {
1165 // Consume devnum.
1166 ConsumeToken();
1167 // Consume colon.
1168 ConsumeToken();
1169
1170 OpenACCIntExprParseResult Res = ParseOpenACCIntExpr(
1171 DK: IsDirective ? OpenACCDirectiveKind::Wait
1172 : OpenACCDirectiveKind::Invalid,
1173 CK: 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(ExpectedTok: tok::colon)) {
1182 Result.Failed = true;
1183 return Result;
1184 }
1185
1186 Result.DevNumExpr = Res.first.get();
1187 }
1188
1189 // [ queues : ]
1190 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::Queues, Tok) &&
1191 NextToken().is(K: 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(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
1204 if (!FirstArg) {
1205 if (ExpectAndConsume(ExpectedTok: tok::comma)) {
1206 Result.Failed = true;
1207 return Result;
1208 }
1209 }
1210 FirstArg = false;
1211
1212 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1213 DK: IsDirective ? OpenACCDirectiveKind::Wait
1214 : OpenACCDirectiveKind::Invalid,
1215 CK: 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(Elt: Res.first.get());
1225 }
1226
1227 return Result;
1228}
1229
1230ExprResult 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(K: tok::identifier)) {
1239 Diag(Tok, DiagID: 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(Id: FuncName.getIdentifierInfo(), IdLoc: 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(S: getCurScope(), SS&: ScopeSpec, TemplateKWLoc,
1253 Id&: Name, /*HasTrailingLParen=*/false,
1254 /*isAddressOfOperand=*/IsAddressOfOperand: false);
1255 }
1256
1257 return getActions().CorrectDelayedTyposInExpr(ER: Res);
1258}
1259
1260ExprResult 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(K: tok::r_paren)) {
1268 Diag(Tok: getCurToken(), DiagID: diag::err_acc_incorrect_bind_arg);
1269 return ExprError();
1270 }
1271
1272 if (tok::isStringLiteral(K: getCurToken().getKind()))
1273 return getActions().CorrectDelayedTyposInExpr(ER: 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)
1286Parser::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(E: Res.get());
1294 if (!Res.isUsable())
1295 return {Res, OpenACCParseCanContinue::Can};
1296
1297 Res = getActions().OpenACC().ActOnVar(CK, VarExpr: Res.get());
1298
1299 return {Res, OpenACCParseCanContinue::Can};
1300}
1301
1302llvm::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(Elt: Res.get());
1308 } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1309 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end, Flags: StopBeforeMatch);
1310 return Vars;
1311 }
1312
1313 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
1314 ExpectAndConsume(ExpectedTok: tok::comma);
1315
1316 auto [Res, CanContinue] = ParseOpenACCVar(CK);
1317
1318 if (Res.isUsable()) {
1319 Vars.push_back(Elt: Res.get());
1320 } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1321 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end, Flags: 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
1332void 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(P&: *this,
1342 Kind: OpenACCSpecialTokenKind::ReadOnly,
1343 DirOrClause: 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(CK: OpenACCClauseKind::Invalid);
1351}
1352
1353Parser::OpenACCDirectiveParseInfo
1354Parser::ParseOpenACCDirective() {
1355 SourceLocation StartLoc = ConsumeAnnotationToken();
1356 SourceLocation DirLoc = getCurToken().getLocation();
1357 OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(P&: *this);
1358
1359 getActions().OpenACC().ActOnConstruct(K: 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(P&: *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(Loc: T.getOpenLocation(), DiagID: 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(Loc: 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, DiagID: 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: DirKind, .StartLoc: StartLoc, .DirLoc: DirLoc,
1413 .EndLoc: SourceLocation{},
1414 .Clauses: 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.
1426Parser::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(K: DirInfo.DirKind,
1434 StartLoc: DirInfo.StartLoc))
1435 return nullptr;
1436
1437 // TODO OpenACC: Do whatever decl parsing is required here.
1438 return DeclGroupPtrTy::make(P: getActions().OpenACC().ActOnEndDeclDirective());
1439}
1440
1441// Parse OpenACC Directive on a Statement.
1442StmtResult 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(K: DirInfo.DirKind,
1449 StartLoc: DirInfo.StartLoc))
1450 return StmtError();
1451
1452 StmtResult AssocStmt;
1453 SemaOpenACC::AssociatedStmtRAII AssocStmtRAII(getActions().OpenACC(),
1454 DirInfo.DirKind);
1455 if (doesDirectiveHaveAssociatedStmt(DirKind: DirInfo.DirKind)) {
1456 ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
1457 ParseScope ACCScope(this, getOpenACCScopeFlags(DirKind: DirInfo.DirKind));
1458
1459 AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(
1460 DirectiveLoc: DirInfo.StartLoc, K: DirInfo.DirKind, AssocStmt: ParseStatement());
1461 }
1462
1463 return getActions().OpenACC().ActOnEndStmtDirective(
1464 K: DirInfo.DirKind, StartLoc: DirInfo.StartLoc, DirLoc: DirInfo.DirLoc, EndLoc: DirInfo.EndLoc,
1465 Clauses: DirInfo.Clauses, AssocStmt);
1466}
1467