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