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