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 LLVM_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
538ExprResult ParseOpenACCConditionalExpr(Parser &P) {
539 // FIXME: It isn't clear if the spec saying 'condition' means the same as
540 // it does in an if/while/etc (See ParseCXXCondition), however as it was
541 // written with Fortran/C in mind, we're going to assume it just means an
542 // 'expression evaluating to boolean'.
543 return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression());
544}
545
546// Skip until we see the end of pragma token, but don't consume it. This is us
547// just giving up on the rest of the pragma so we can continue executing. We
548// have to do this because 'SkipUntil' considers paren balancing, which isn't
549// what we want.
550void SkipUntilEndOfDirective(Parser &P) {
551 while (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
552 P.ConsumeAnyToken();
553}
554
555bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) {
556 switch (DirKind) {
557 default:
558 return false;
559 case OpenACCDirectiveKind::Parallel:
560 case OpenACCDirectiveKind::Serial:
561 case OpenACCDirectiveKind::Kernels:
562 return true;
563 }
564 llvm_unreachable("Unhandled directive->assoc stmt");
565}
566
567unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) {
568 switch (DirKind) {
569 case OpenACCDirectiveKind::Parallel:
570 case OpenACCDirectiveKind::Serial:
571 case OpenACCDirectiveKind::Kernels:
572 // Mark this as a BreakScope/ContinueScope as well as a compute construct
573 // so that we can diagnose trying to 'break'/'continue' inside of one.
576 case OpenACCDirectiveKind::Invalid:
577 llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
578 default:
579 break;
580 }
581 return 0;
582}
583
584} // namespace
585
586Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
587 return {nullptr, OpenACCParseCanContinue::Can};
588}
589
590Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
591 return {nullptr, OpenACCParseCanContinue::Cannot};
592}
593
594Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {
595 return {Clause, OpenACCParseCanContinue::Can};
596}
597
598// OpenACC 3.3, section 1.7:
599// To simplify the specification and convey appropriate constraint information,
600// a pqr-list is a comma-separated list of pdr items. The one exception is a
601// clause-list, which is a list of one or more clauses optionally separated by
602// commas.
604Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
606 bool FirstClause = true;
607 while (getCurToken().isNot(tok::annot_pragma_openacc_end)) {
608 // Comma is optional in a clause-list.
609 if (!FirstClause && getCurToken().is(tok::comma))
610 ConsumeToken();
611 FirstClause = false;
612
613 OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind);
614 if (OpenACCClause *Clause = Result.getPointer()) {
615 Clauses.push_back(Clause);
616 } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) {
617 // Recovering from a bad clause is really difficult, so we just give up on
618 // error.
619 SkipUntilEndOfDirective(*this);
620 return Clauses;
621 }
622 }
623 return Clauses;
624}
625
626ExprResult Parser::ParseOpenACCIntExpr() {
627 // FIXME: this is required to be an integer expression (or dependent), so we
628 // should ensure that is the case by passing this to SEMA here.
630}
631
632bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) {
633 // FIXME: Future clauses will require 'special word' parsing, check for one,
634 // then parse it based on whether it is a clause that requires a 'special
635 // word'.
636 (void)Kind;
637
638 // If the var parsing fails, skip until the end of the directive as this is
639 // an expression and gets messy if we try to continue otherwise.
640 if (ParseOpenACCVar())
641 return true;
642
643 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
644 ExpectAndConsume(tok::comma);
645
646 // If the var parsing fails, skip until the end of the directive as this is
647 // an expression and gets messy if we try to continue otherwise.
648 if (ParseOpenACCVar())
649 return true;
650 }
651 return false;
652}
653
654/// OpenACC 3.3 Section 2.4:
655/// The argument to the device_type clause is a comma-separated list of one or
656/// more device architecture name identifiers, or an asterisk.
657///
658/// The syntax of the device_type clause is
659/// device_type( * )
660/// device_type( device-type-list )
661///
662/// The device_type clause may be abbreviated to dtype.
663bool Parser::ParseOpenACCDeviceTypeList() {
664
665 if (expectIdentifierOrKeyword(*this)) {
666 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
668 return false;
669 }
670 ConsumeToken();
671
672 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
673 ExpectAndConsume(tok::comma);
674
675 if (expectIdentifierOrKeyword(*this)) {
676 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
678 return false;
679 }
680 ConsumeToken();
681 }
682 return false;
683}
684
685/// OpenACC 3.3 Section 2.9:
686/// size-expr is one of:
687// *
688// int-expr
689// Note that this is specified under 'gang-arg-list', but also applies to 'tile'
690// via reference.
691bool Parser::ParseOpenACCSizeExpr() {
692 // FIXME: Ensure these are constant expressions.
693
694 // The size-expr ends up being ambiguous when only looking at the current
695 // token, as it could be a deref of a variable/expression.
696 if (getCurToken().is(tok::star) &&
697 NextToken().isOneOf(tok::comma, tok::r_paren,
698 tok::annot_pragma_openacc_end)) {
699 ConsumeToken();
700 return false;
701 }
702
703 return getActions()
705 .isInvalid();
706}
707
708bool Parser::ParseOpenACCSizeExprList() {
709 if (ParseOpenACCSizeExpr()) {
710 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
712 return false;
713 }
714
715 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
716 ExpectAndConsume(tok::comma);
717
718 if (ParseOpenACCSizeExpr()) {
719 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
721 return false;
722 }
723 }
724 return false;
725}
726
727/// OpenACC 3.3 Section 2.9:
728///
729/// where gang-arg is one of:
730/// [num:]int-expr
731/// dim:int-expr
732/// static:size-expr
733bool Parser::ParseOpenACCGangArg() {
734
735 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) &&
736 NextToken().is(tok::colon)) {
737 // 'static' just takes a size-expr, which is an int-expr or an asterisk.
738 ConsumeToken();
739 ConsumeToken();
740 return ParseOpenACCSizeExpr();
741 }
742
743 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) &&
744 NextToken().is(tok::colon)) {
745 ConsumeToken();
746 ConsumeToken();
747 return ParseOpenACCIntExpr().isInvalid();
748 }
749
750 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) &&
751 NextToken().is(tok::colon)) {
752 ConsumeToken();
753 ConsumeToken();
754 // Fallthrough to the 'int-expr' handling for when 'num' is omitted.
755 }
756 // This is just the 'num' case where 'num' is optional.
757 return ParseOpenACCIntExpr().isInvalid();
758}
759
760bool Parser::ParseOpenACCGangArgList() {
761 if (ParseOpenACCGangArg()) {
762 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
764 return false;
765 }
766
767 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
768 ExpectAndConsume(tok::comma);
769
770 if (ParseOpenACCGangArg()) {
771 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
773 return false;
774 }
775 }
776 return false;
777}
778
779// The OpenACC Clause List is a comma or space-delimited list of clauses (see
780// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't
781// really have its owner grammar and each individual one has its own definition.
782// However, they all are named with a single-identifier (or auto/default!)
783// token, followed in some cases by either braces or parens.
784Parser::OpenACCClauseParseResult
785Parser::ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
786 OpenACCDirectiveKind DirKind) {
787 // A number of clause names are actually keywords, so accept a keyword that
788 // can be converted to a name.
789 if (expectIdentifierOrKeyword(*this))
790 return OpenACCCannotContinue();
791
792 OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken());
793
794 if (Kind == OpenACCClauseKind::Invalid) {
795 Diag(getCurToken(), diag::err_acc_invalid_clause)
797 return OpenACCCannotContinue();
798 }
799
800 // Consume the clause name.
801 SourceLocation ClauseLoc = ConsumeToken();
802
803 return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);
804}
805
806Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
807 ArrayRef<const OpenACCClause *> ExistingClauses,
808 OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind,
809 SourceLocation ClauseLoc) {
810 BalancedDelimiterTracker Parens(*this, tok::l_paren,
811 tok::annot_pragma_openacc_end);
812 SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc);
813
814 if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
815 ParsedClause.setLParenLoc(getCurToken().getLocation());
816 if (Parens.expectAndConsume()) {
817 // We are missing a paren, so assume that the person just forgot the
818 // parameter. Return 'false' so we try to continue on and parse the next
819 // clause.
820 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
822 return OpenACCCanContinue();
823 }
824
825 switch (ClauseKind) {
827 Token DefKindTok = getCurToken();
828
829 if (expectIdentifierOrKeyword(*this))
830 break;
831
832 ConsumeToken();
833
835 getOpenACCDefaultClauseKind(DefKindTok);
836
838 Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
839 else
840 ParsedClause.setDefaultDetails(DefKind);
841
842 break;
843 }
845 ExprResult CondExpr = ParseOpenACCConditionalExpr(*this);
846
847 if (CondExpr.isInvalid()) {
848 Parens.skipToEnd();
849 return OpenACCCanContinue();
850 }
851 break;
852 }
854 tryParseAndConsumeSpecialTokenKind(
855 *this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind);
856 if (ParseOpenACCClauseVarList(ClauseKind)) {
857 Parens.skipToEnd();
858 return OpenACCCanContinue();
859 }
860 break;
863 tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Zero,
864 ClauseKind);
865 if (ParseOpenACCClauseVarList(ClauseKind)) {
866 Parens.skipToEnd();
867 return OpenACCCanContinue();
868 }
869 break;
871 // If we're missing a clause-kind (or it is invalid), see if we can parse
872 // the var-list anyway.
873 ParseReductionOperator(*this);
874 if (ParseOpenACCClauseVarList(ClauseKind)) {
875 Parens.skipToEnd();
876 return OpenACCCanContinue();
877 }
878 break;
880 // The 'self' clause is a var-list instead of a 'condition' in the case of
881 // the 'update' clause, so we have to handle it here. U se an assert to
882 // make sure we get the right differentiator.
883 assert(DirKind == OpenACCDirectiveKind::Update);
884 LLVM_FALLTHROUGH;
899 if (ParseOpenACCClauseVarList(ClauseKind)) {
900 Parens.skipToEnd();
901 return OpenACCCanContinue();
902 }
903 break;
905 tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Force,
906 ClauseKind);
907 ExprResult NumLoops =
909 if (NumLoops.isInvalid()) {
910 Parens.skipToEnd();
911 return OpenACCCanContinue();
912 }
913 break;
914 }
916 ExprResult BindArg = ParseOpenACCBindClauseArgument();
917 if (BindArg.isInvalid()) {
918 Parens.skipToEnd();
919 return OpenACCCanContinue();
920 }
921 break;
922 }
928 ExprResult IntExpr = ParseOpenACCIntExpr();
929 if (IntExpr.isInvalid()) {
930 Parens.skipToEnd();
931 return OpenACCCanContinue();
932 }
933 break;
934 }
937 if (getCurToken().is(tok::star)) {
938 // FIXME: We want to mark that this is an 'everything else' type of
939 // device_type in Sema.
940 ConsumeToken();
941 } else if (ParseOpenACCDeviceTypeList()) {
942 Parens.skipToEnd();
943 return OpenACCCanContinue();
944 }
945 break;
947 if (ParseOpenACCSizeExprList()) {
948 Parens.skipToEnd();
949 return OpenACCCanContinue();
950 }
951 break;
952 default:
953 llvm_unreachable("Not a required parens type?");
954 }
955
956 ParsedClause.setEndLoc(getCurToken().getLocation());
957
958 if (Parens.consumeClose())
959 return OpenACCCannotContinue();
960
961 } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
962 ParsedClause.setLParenLoc(getCurToken().getLocation());
963 if (!Parens.consumeOpen()) {
964 switch (ClauseKind) {
966 assert(DirKind != OpenACCDirectiveKind::Update);
967 ExprResult CondExpr = ParseOpenACCConditionalExpr(*this);
968
969 if (CondExpr.isInvalid()) {
970 Parens.skipToEnd();
971 return OpenACCCanContinue();
972 }
973 break;
974 }
977 tryParseAndConsumeSpecialTokenKind(*this,
978 ClauseKind ==
980 ? OpenACCSpecialTokenKind::Length
981 : OpenACCSpecialTokenKind::Num,
982 ClauseKind);
983 ExprResult IntExpr = ParseOpenACCIntExpr();
984 if (IntExpr.isInvalid()) {
985 Parens.skipToEnd();
986 return OpenACCCanContinue();
987 }
988 break;
989 }
991 ExprResult AsyncArg = ParseOpenACCAsyncArgument();
992 if (AsyncArg.isInvalid()) {
993 Parens.skipToEnd();
994 return OpenACCCanContinue();
995 }
996 break;
997 }
999 if (ParseOpenACCGangArgList()) {
1000 Parens.skipToEnd();
1001 return OpenACCCanContinue();
1002 }
1003 break;
1005 if (ParseOpenACCWaitArgument()) {
1006 Parens.skipToEnd();
1007 return OpenACCCanContinue();
1008 }
1009 break;
1010 default:
1011 llvm_unreachable("Not an optional parens type?");
1012 }
1013 ParsedClause.setEndLoc(getCurToken().getLocation());
1014 if (Parens.consumeClose())
1015 return OpenACCCannotContinue();
1016 }
1017 }
1018 return OpenACCSuccess(
1019 Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause));
1020}
1021
1022/// OpenACC 3.3 section 2.16:
1023/// In this section and throughout the specification, the term async-argument
1024/// means a nonnegative scalar integer expression (int for C or C++, integer for
1025/// Fortran), or one of the special values acc_async_noval or acc_async_sync, as
1026/// defined in the C header file and the Fortran openacc module. The special
1027/// values are negative values, so as not to conflict with a user-specified
1028/// nonnegative async-argument.
1029ExprResult Parser::ParseOpenACCAsyncArgument() {
1031}
1032
1033/// OpenACC 3.3, section 2.16:
1034/// In this section and throughout the specification, the term wait-argument
1035/// means:
1036/// [ devnum : int-expr : ] [ queues : ] async-argument-list
1037bool Parser::ParseOpenACCWaitArgument() {
1038 // [devnum : int-expr : ]
1039 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
1040 NextToken().is(tok::colon)) {
1041 // Consume devnum.
1042 ConsumeToken();
1043 // Consume colon.
1044 ConsumeToken();
1045
1046 ExprResult IntExpr = ParseOpenACCIntExpr();
1047 if (IntExpr.isInvalid())
1048 return true;
1049
1050 if (ExpectAndConsume(tok::colon))
1051 return true;
1052 }
1053
1054 // [ queues : ]
1055 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
1056 NextToken().is(tok::colon)) {
1057 // Consume queues.
1058 ConsumeToken();
1059 // Consume colon.
1060 ConsumeToken();
1061 }
1062
1063 // OpenACC 3.3, section 2.16:
1064 // the term 'async-argument' means a nonnegative scalar integer expression, or
1065 // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined
1066 // in the C header file and the Fortran opacc module.
1067 bool FirstArg = true;
1068 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1069 if (!FirstArg) {
1070 if (ExpectAndConsume(tok::comma))
1071 return true;
1072 }
1073 FirstArg = false;
1074
1075 ExprResult CurArg = ParseOpenACCAsyncArgument();
1076
1077 if (CurArg.isInvalid())
1078 return true;
1079 }
1080
1081 return false;
1082}
1083
1084ExprResult Parser::ParseOpenACCIDExpression() {
1085 ExprResult Res;
1086 if (getLangOpts().CPlusPlus) {
1087 Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true);
1088 } else {
1089 // There isn't anything quite the same as ParseCXXIdExpression for C, so we
1090 // need to get the identifier, then call into Sema ourselves.
1091
1092 if (Tok.isNot(tok::identifier)) {
1093 Diag(Tok, diag::err_expected) << tok::identifier;
1094 return ExprError();
1095 }
1096
1097 Token FuncName = getCurToken();
1098 UnqualifiedId Name;
1099 CXXScopeSpec ScopeSpec;
1100 SourceLocation TemplateKWLoc;
1101 Name.setIdentifier(FuncName.getIdentifierInfo(), ConsumeToken());
1102
1103 // Ensure this is a valid identifier. We don't accept causing implicit
1104 // function declarations per the spec, so always claim to not have trailing
1105 // L Paren.
1106 Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
1107 Name, /*HasTrailingLParen=*/false,
1108 /*isAddressOfOperand=*/false);
1109 }
1110
1112}
1113
1114ExprResult Parser::ParseOpenACCBindClauseArgument() {
1115 // OpenACC 3.3 section 2.15:
1116 // The bind clause specifies the name to use when calling the procedure on a
1117 // device other than the host. If the name is specified as an identifier, it
1118 // is called as if that name were specified in the language being compiled. If
1119 // the name is specified as a string, the string is used for the procedure
1120 // name unmodified.
1121 if (getCurToken().is(tok::r_paren)) {
1122 Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
1123 return ExprError();
1124 }
1125
1128 /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
1129
1130 return ParseOpenACCIDExpression();
1131}
1132
1133/// OpenACC 3.3, section 1.6:
1134/// In this spec, a 'var' (in italics) is one of the following:
1135/// - a variable name (a scalar, array, or compisite variable name)
1136/// - a subarray specification with subscript ranges
1137/// - an array element
1138/// - a member of a composite variable
1139/// - a common block name between slashes (fortran only)
1140bool Parser::ParseOpenACCVar() {
1141 OpenACCArraySectionRAII ArraySections(*this);
1142 ExprResult Res =
1144 return Res.isInvalid();
1145}
1146
1147/// OpenACC 3.3, section 2.10:
1148/// In C and C++, the syntax of the cache directive is:
1149///
1150/// #pragma acc cache ([readonly:]var-list) new-line
1151void Parser::ParseOpenACCCacheVarList() {
1152 // If this is the end of the line, just return 'false' and count on the close
1153 // paren diagnostic to catch the issue.
1154 if (getCurToken().isAnnotation())
1155 return;
1156
1157 // The VarList is an optional `readonly:` followed by a list of a variable
1158 // specifications. Consume something that looks like a 'tag', and diagnose if
1159 // it isn't 'readonly'.
1160 if (tryParseAndConsumeSpecialTokenKind(*this,
1161 OpenACCSpecialTokenKind::ReadOnly,
1163 // FIXME: Record that this is a 'readonly' so that we can use that during
1164 // Sema/AST generation.
1165 }
1166
1167 bool FirstArray = true;
1168 while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1169 if (!FirstArray)
1170 ExpectAndConsume(tok::comma);
1171 FirstArray = false;
1172
1173 // OpenACC 3.3, section 2.10:
1174 // A 'var' in a cache directive must be a single array element or a simple
1175 // subarray. In C and C++, a simple subarray is an array name followed by
1176 // an extended array range specification in brackets, with a start and
1177 // length such as:
1178 //
1179 // arr[lower:length]
1180 //
1181 if (ParseOpenACCVar())
1182 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma,
1184 }
1185}
1186
1187Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
1188 SourceLocation StartLoc = getCurToken().getLocation();
1189 OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);
1190
1191 getActions().OpenACC().ActOnConstruct(DirKind, StartLoc);
1192
1193 // Once we've parsed the construct/directive name, some have additional
1194 // specifiers that need to be taken care of. Atomic has an 'atomic-clause'
1195 // that needs to be parsed.
1196 if (DirKind == OpenACCDirectiveKind::Atomic)
1197 ParseOpenACCAtomicKind(*this);
1198
1199 // We've successfully parsed the construct/directive name, however a few of
1200 // the constructs have optional parens that contain further details.
1201 BalancedDelimiterTracker T(*this, tok::l_paren,
1202 tok::annot_pragma_openacc_end);
1203
1204 if (!T.consumeOpen()) {
1205 switch (DirKind) {
1206 default:
1207 Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren);
1208 T.skipToEnd();
1209 break;
1211 // Routine has an optional paren-wrapped name of a function in the local
1212 // scope. We parse the name, emitting any diagnostics
1213 ExprResult RoutineName = ParseOpenACCIDExpression();
1214 // If the routine name is invalid, just skip until the closing paren to
1215 // recover more gracefully.
1216 if (RoutineName.isInvalid())
1217 T.skipToEnd();
1218 else
1219 T.consumeClose();
1220 break;
1221 }
1223 ParseOpenACCCacheVarList();
1224 // The ParseOpenACCCacheVarList function manages to recover from failures,
1225 // so we can always consume the close.
1226 T.consumeClose();
1227 break;
1229 // OpenACC has an optional paren-wrapped 'wait-argument'.
1230 if (ParseOpenACCWaitArgument())
1231 T.skipToEnd();
1232 else
1233 T.consumeClose();
1234 break;
1235 }
1236 } else if (DirKind == OpenACCDirectiveKind::Cache) {
1237 // Cache's paren var-list is required, so error here if it isn't provided.
1238 // We know that the consumeOpen above left the first non-paren here, so
1239 // diagnose, then continue as if it was completely omitted.
1240 Diag(Tok, diag::err_expected) << tok::l_paren;
1241 }
1242
1243 // Parses the list of clauses, if present, plus set up return value.
1244 OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, SourceLocation{},
1245 ParseOpenACCClauseList(DirKind)};
1246
1247 assert(Tok.is(tok::annot_pragma_openacc_end) &&
1248 "Didn't parse all OpenACC Clauses");
1249 ParseInfo.EndLoc = ConsumeAnnotationToken();
1250 assert(ParseInfo.EndLoc.isValid() &&
1251 "Terminating annotation token not present");
1252
1253 return ParseInfo;
1254}
1255
1256// Parse OpenACC directive on a declaration.
1258 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1259
1260 ParsingOpenACCDirectiveRAII DirScope(*this);
1261 ConsumeAnnotationToken();
1262
1263 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1264
1265 if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind,
1266 DirInfo.StartLoc))
1267 return nullptr;
1268
1269 // TODO OpenACC: Do whatever decl parsing is required here.
1270 return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective());
1271}
1272
1273// Parse OpenACC Directive on a Statement.
1275 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1276
1277 ParsingOpenACCDirectiveRAII DirScope(*this);
1278 ConsumeAnnotationToken();
1279
1280 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1281 if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind,
1282 DirInfo.StartLoc))
1283 return StmtError();
1284
1285 StmtResult AssocStmt;
1286
1287 if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {
1288 ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
1289 ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind));
1290
1291 AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(DirInfo.DirKind,
1292 ParseStatement());
1293 }
1294
1296 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, DirInfo.Clauses,
1297 AssocStmt);
1298}
StringRef P
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:1114
Defines some OpenACC-specific enums and functions.
static constexpr bool isOneOf()
This file declares semantic analysis for OpenACC constructs and clauses.
bool isInvalid() const
Definition: Ownership.h:166
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
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:21
ParseScope - Introduces a new scope for parsing.
Definition: Parser.h:1138
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:55
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:515
DeclGroupPtrTy ParseOpenACCDirectiveDecl()
Placeholder for now, should just ignore the directives after emitting a diagnostic.
Sema & getActions() const
Definition: Parser.h:465
ExprResult ParseConstantExpression()
Definition: ParseExpr.cpp:228
StmtResult ParseOpenACCDirectiveStmt()
Scope * getCurScope() const
Definition: Parser.h:469
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:1261
const Token & getCurToken() const
Definition: Parser.h:468
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
Definition: ParseExpr.cpp:164
const LangOptions & getLangOpts() const
Definition: Parser.h:462
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
Definition: Parser.h:1242
ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral=false)
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
Definition: Parser.h:839
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
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.
Definition: SemaOpenACC.cpp:69
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...
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:2686
SemaOpenACC & OpenACC()
Definition: Sema.h:972
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:1024
bool Zero(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1840
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:158
@ 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:149
StmtResult StmtError()
Definition: Ownership.h:265
@ Result
The result type of a method or function.
OpenACCDefaultClauseKind
Definition: OpenACCKinds.h:413
@ Invalid
Not a valid option.
OpenACCDirectiveKind
Definition: OpenACCKinds.h:25
ExprResult ExprError()
Definition: Ownership.h:264
const FunctionProtoType * T
OpenACCReductionOperator
Definition: OpenACCKinds.h:446
@ 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