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