1//===--- ParseOpenACC.cpp - OpenACC-specific parsing support --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the parsing logic for OpenACC language features.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Basic/OpenACCKinds.h"
14#include "clang/Parse/ParseDiagnostic.h"
15#include "clang/Parse/Parser.h"
16#include "clang/Parse/RAIIObjectsForParser.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/StringSwitch.h"
19
20using namespace clang;
21using namespace llvm;
22
23namespace {
24// An enum that contains the extended 'partial' parsed variants. This type
25// should never escape the initial parse functionality, but is useful for
26// simplifying the implementation.
27enum class OpenACCDirectiveKindEx {
28 Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid),
29 // 'enter data' and 'exit data'
30 Enter,
31 Exit,
32};
33
34// Translate single-token string representations to the OpenACC Directive Kind.
35// This doesn't completely comprehend 'Compound Constructs' (as it just
36// identifies the first token), and doesn't fully handle 'enter data', 'exit
37// data', nor any of the 'atomic' variants, just the first token of each. So
38// this should only be used by `ParseOpenACCDirectiveKind`.
39OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {
40 if (!Tok.is(K: tok::identifier))
41 return OpenACCDirectiveKindEx::Invalid;
42 OpenACCDirectiveKind DirKind =
43 llvm::StringSwitch<OpenACCDirectiveKind>(
44 Tok.getIdentifierInfo()->getName())
45 .Case(S: "parallel", Value: OpenACCDirectiveKind::Parallel)
46 .Case(S: "serial", Value: OpenACCDirectiveKind::Serial)
47 .Case(S: "kernels", Value: OpenACCDirectiveKind::Kernels)
48 .Case(S: "data", Value: OpenACCDirectiveKind::Data)
49 .Case(S: "host_data", Value: OpenACCDirectiveKind::HostData)
50 .Case(S: "loop", Value: OpenACCDirectiveKind::Loop)
51 .Case(S: "cache", Value: OpenACCDirectiveKind::Cache)
52 .Case(S: "atomic", Value: OpenACCDirectiveKind::Atomic)
53 .Case(S: "routine", Value: OpenACCDirectiveKind::Routine)
54 .Case(S: "declare", Value: OpenACCDirectiveKind::Declare)
55 .Case(S: "init", Value: OpenACCDirectiveKind::Init)
56 .Case(S: "shutdown", Value: OpenACCDirectiveKind::Shutdown)
57 .Case(S: "set", Value: OpenACCDirectiveKind::Set)
58 .Case(S: "update", Value: OpenACCDirectiveKind::Update)
59 .Case(S: "wait", Value: OpenACCDirectiveKind::Wait)
60 .Default(Value: OpenACCDirectiveKind::Invalid);
61
62 if (DirKind != OpenACCDirectiveKind::Invalid)
63 return static_cast<OpenACCDirectiveKindEx>(DirKind);
64
65 return llvm::StringSwitch<OpenACCDirectiveKindEx>(
66 Tok.getIdentifierInfo()->getName())
67 .Case(S: "enter", Value: OpenACCDirectiveKindEx::Enter)
68 .Case(S: "exit", Value: OpenACCDirectiveKindEx::Exit)
69 .Default(Value: OpenACCDirectiveKindEx::Invalid);
70}
71
72// Translate single-token string representations to the OpenCC Clause Kind.
73OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
74 // auto is a keyword in some language modes, so make sure we parse it
75 // correctly.
76 if (Tok.is(K: tok::kw_auto))
77 return OpenACCClauseKind::Auto;
78
79 // default is a keyword, so make sure we parse it correctly.
80 if (Tok.is(K: tok::kw_default))
81 return OpenACCClauseKind::Default;
82
83 // if is also a keyword, make sure we parse it correctly.
84 if (Tok.is(K: tok::kw_if))
85 return OpenACCClauseKind::If;
86
87 if (!Tok.is(K: tok::identifier))
88 return OpenACCClauseKind::Invalid;
89
90 return llvm::StringSwitch<OpenACCClauseKind>(
91 Tok.getIdentifierInfo()->getName())
92 .Case(S: "async", Value: OpenACCClauseKind::Async)
93 .Case(S: "attach", Value: OpenACCClauseKind::Attach)
94 .Case(S: "auto", Value: OpenACCClauseKind::Auto)
95 .Case(S: "bind", Value: OpenACCClauseKind::Bind)
96 .Case(S: "create", Value: OpenACCClauseKind::Create)
97 .Case(S: "collapse", Value: OpenACCClauseKind::Collapse)
98 .Case(S: "copy", Value: OpenACCClauseKind::Copy)
99 .Case(S: "copyin", Value: OpenACCClauseKind::CopyIn)
100 .Case(S: "copyout", Value: OpenACCClauseKind::CopyOut)
101 .Case(S: "default", Value: OpenACCClauseKind::Default)
102 .Case(S: "default_async", Value: OpenACCClauseKind::DefaultAsync)
103 .Case(S: "delete", Value: OpenACCClauseKind::Delete)
104 .Case(S: "detach", Value: OpenACCClauseKind::Detach)
105 .Case(S: "device", Value: OpenACCClauseKind::Device)
106 .Case(S: "device_num", Value: OpenACCClauseKind::DeviceNum)
107 .Case(S: "device_resident", Value: OpenACCClauseKind::DeviceResident)
108 .Case(S: "device_type", Value: OpenACCClauseKind::DeviceType)
109 .Case(S: "deviceptr", Value: OpenACCClauseKind::DevicePtr)
110 .Case(S: "dtype", Value: OpenACCClauseKind::DType)
111 .Case(S: "finalize", Value: OpenACCClauseKind::Finalize)
112 .Case(S: "firstprivate", Value: OpenACCClauseKind::FirstPrivate)
113 .Case(S: "gang", Value: OpenACCClauseKind::Gang)
114 .Case(S: "host", Value: OpenACCClauseKind::Host)
115 .Case(S: "if", Value: OpenACCClauseKind::If)
116 .Case(S: "if_present", Value: OpenACCClauseKind::IfPresent)
117 .Case(S: "independent", Value: OpenACCClauseKind::Independent)
118 .Case(S: "link", Value: OpenACCClauseKind::Link)
119 .Case(S: "no_create", Value: OpenACCClauseKind::NoCreate)
120 .Case(S: "num_gangs", Value: OpenACCClauseKind::NumGangs)
121 .Case(S: "num_workers", Value: OpenACCClauseKind::NumWorkers)
122 .Case(S: "nohost", Value: OpenACCClauseKind::NoHost)
123 .Case(S: "present", Value: OpenACCClauseKind::Present)
124 .Case(S: "private", Value: OpenACCClauseKind::Private)
125 .Case(S: "reduction", Value: OpenACCClauseKind::Reduction)
126 .Case(S: "self", Value: OpenACCClauseKind::Self)
127 .Case(S: "seq", Value: OpenACCClauseKind::Seq)
128 .Case(S: "tile", Value: OpenACCClauseKind::Tile)
129 .Case(S: "use_device", Value: OpenACCClauseKind::UseDevice)
130 .Case(S: "vector", Value: OpenACCClauseKind::Vector)
131 .Case(S: "vector_length", Value: OpenACCClauseKind::VectorLength)
132 .Case(S: "wait", Value: OpenACCClauseKind::Wait)
133 .Case(S: "worker", Value: OpenACCClauseKind::Worker)
134 .Default(Value: OpenACCClauseKind::Invalid);
135}
136
137// Since 'atomic' is effectively a compound directive, this will decode the
138// second part of the directive.
139OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
140 if (!Tok.is(K: tok::identifier))
141 return OpenACCAtomicKind::Invalid;
142 return llvm::StringSwitch<OpenACCAtomicKind>(
143 Tok.getIdentifierInfo()->getName())
144 .Case(S: "read", Value: OpenACCAtomicKind::Read)
145 .Case(S: "write", Value: OpenACCAtomicKind::Write)
146 .Case(S: "update", Value: OpenACCAtomicKind::Update)
147 .Case(S: "capture", Value: OpenACCAtomicKind::Capture)
148 .Default(Value: OpenACCAtomicKind::Invalid);
149}
150
151OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) {
152 if (!Tok.is(K: tok::identifier))
153 return OpenACCDefaultClauseKind::Invalid;
154
155 return llvm::StringSwitch<OpenACCDefaultClauseKind>(
156 Tok.getIdentifierInfo()->getName())
157 .Case(S: "none", Value: OpenACCDefaultClauseKind::None)
158 .Case(S: "present", Value: OpenACCDefaultClauseKind::Present)
159 .Default(Value: OpenACCDefaultClauseKind::Invalid);
160}
161
162enum class OpenACCSpecialTokenKind {
163 ReadOnly,
164 DevNum,
165 Queues,
166 Zero,
167 Force,
168 Num,
169 Length,
170 Dim,
171 Static,
172};
173
174bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {
175 if (Tok.is(K: tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static)
176 return true;
177
178 if (!Tok.is(K: tok::identifier))
179 return false;
180
181 switch (Kind) {
182 case OpenACCSpecialTokenKind::ReadOnly:
183 return Tok.getIdentifierInfo()->isStr(Str: "readonly");
184 case OpenACCSpecialTokenKind::DevNum:
185 return Tok.getIdentifierInfo()->isStr(Str: "devnum");
186 case OpenACCSpecialTokenKind::Queues:
187 return Tok.getIdentifierInfo()->isStr(Str: "queues");
188 case OpenACCSpecialTokenKind::Zero:
189 return Tok.getIdentifierInfo()->isStr(Str: "zero");
190 case OpenACCSpecialTokenKind::Force:
191 return Tok.getIdentifierInfo()->isStr(Str: "force");
192 case OpenACCSpecialTokenKind::Num:
193 return Tok.getIdentifierInfo()->isStr(Str: "num");
194 case OpenACCSpecialTokenKind::Length:
195 return Tok.getIdentifierInfo()->isStr(Str: "length");
196 case OpenACCSpecialTokenKind::Dim:
197 return Tok.getIdentifierInfo()->isStr(Str: "dim");
198 case OpenACCSpecialTokenKind::Static:
199 return Tok.getIdentifierInfo()->isStr(Str: "static");
200 }
201 llvm_unreachable("Unknown 'Kind' Passed");
202}
203
204/// Used for cases where we have a token we want to check against an
205/// 'identifier-like' token, but don't want to give awkward error messages in
206/// cases where it is accidentially a keyword.
207bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) {
208 if (Tok.is(K: tok::identifier))
209 return true;
210
211 if (!Tok.isAnnotation() && Tok.getIdentifierInfo() &&
212 Tok.getIdentifierInfo()->isKeyword(LangOpts: P.getLangOpts()))
213 return true;
214
215 return false;
216}
217
218/// Parses and consumes an identifer followed immediately by a single colon, and
219/// diagnoses if it is not the 'special token' kind that we require. Used when
220/// the tag is the only valid value.
221/// Return 'true' if the special token was matched, false if no special token,
222/// or an invalid special token was found.
223template <typename DirOrClauseTy>
224bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind,
225 DirOrClauseTy DirOrClause) {
226 Token IdentTok = P.getCurToken();
227 // If this is an identifier-like thing followed by ':', it is one of the
228 // OpenACC 'special' name tags, so consume it.
229 if (isTokenIdentifierOrKeyword(P, Tok: IdentTok) && P.NextToken().is(K: tok::colon)) {
230 P.ConsumeToken();
231 P.ConsumeToken();
232
233 if (!isOpenACCSpecialToken(Kind, Tok: IdentTok)) {
234 P.Diag(IdentTok, diag::err_acc_invalid_tag_kind)
235 << IdentTok.getIdentifierInfo() << DirOrClause
236 << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>;
237 return false;
238 }
239
240 return true;
241 }
242
243 return false;
244}
245
246bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
247 if (!Tok.is(K: tok::identifier))
248 return false;
249
250 switch (Kind) {
251 case OpenACCDirectiveKind::Parallel:
252 return Tok.getIdentifierInfo()->isStr(Str: "parallel");
253 case OpenACCDirectiveKind::Serial:
254 return Tok.getIdentifierInfo()->isStr(Str: "serial");
255 case OpenACCDirectiveKind::Kernels:
256 return Tok.getIdentifierInfo()->isStr(Str: "kernels");
257 case OpenACCDirectiveKind::Data:
258 return Tok.getIdentifierInfo()->isStr(Str: "data");
259 case OpenACCDirectiveKind::HostData:
260 return Tok.getIdentifierInfo()->isStr(Str: "host_data");
261 case OpenACCDirectiveKind::Loop:
262 return Tok.getIdentifierInfo()->isStr(Str: "loop");
263 case OpenACCDirectiveKind::Cache:
264 return Tok.getIdentifierInfo()->isStr(Str: "cache");
265
266 case OpenACCDirectiveKind::ParallelLoop:
267 case OpenACCDirectiveKind::SerialLoop:
268 case OpenACCDirectiveKind::KernelsLoop:
269 case OpenACCDirectiveKind::EnterData:
270 case OpenACCDirectiveKind::ExitData:
271 return false;
272
273 case OpenACCDirectiveKind::Atomic:
274 return Tok.getIdentifierInfo()->isStr(Str: "atomic");
275 case OpenACCDirectiveKind::Routine:
276 return Tok.getIdentifierInfo()->isStr(Str: "routine");
277 case OpenACCDirectiveKind::Declare:
278 return Tok.getIdentifierInfo()->isStr(Str: "declare");
279 case OpenACCDirectiveKind::Init:
280 return Tok.getIdentifierInfo()->isStr(Str: "init");
281 case OpenACCDirectiveKind::Shutdown:
282 return Tok.getIdentifierInfo()->isStr(Str: "shutdown");
283 case OpenACCDirectiveKind::Set:
284 return Tok.getIdentifierInfo()->isStr(Str: "set");
285 case OpenACCDirectiveKind::Update:
286 return Tok.getIdentifierInfo()->isStr(Str: "update");
287 case OpenACCDirectiveKind::Wait:
288 return Tok.getIdentifierInfo()->isStr(Str: "wait");
289 case OpenACCDirectiveKind::Invalid:
290 return false;
291 }
292 llvm_unreachable("Unknown 'Kind' Passed");
293}
294
295OpenACCReductionOperator ParseReductionOperator(Parser &P) {
296 // If there is no colon, treat as if the reduction operator was missing, else
297 // we probably will not recover from it in the case where an expression starts
298 // with one of the operator tokens.
299 if (P.NextToken().isNot(K: tok::colon)) {
300 P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator);
301 return OpenACCReductionOperator::Invalid;
302 }
303 Token ReductionKindTok = P.getCurToken();
304 // Consume both the kind and the colon.
305 P.ConsumeToken();
306 P.ConsumeToken();
307
308 switch (ReductionKindTok.getKind()) {
309 case tok::plus:
310 return OpenACCReductionOperator::Addition;
311 case tok::star:
312 return OpenACCReductionOperator::Multiplication;
313 case tok::amp:
314 return OpenACCReductionOperator::BitwiseAnd;
315 case tok::pipe:
316 return OpenACCReductionOperator::BitwiseOr;
317 case tok::caret:
318 return OpenACCReductionOperator::BitwiseXOr;
319 case tok::ampamp:
320 return OpenACCReductionOperator::And;
321 case tok::pipepipe:
322 return OpenACCReductionOperator::Or;
323 case tok::identifier:
324 if (ReductionKindTok.getIdentifierInfo()->isStr(Str: "max"))
325 return OpenACCReductionOperator::Max;
326 if (ReductionKindTok.getIdentifierInfo()->isStr(Str: "min"))
327 return OpenACCReductionOperator::Min;
328 LLVM_FALLTHROUGH;
329 default:
330 P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
331 return OpenACCReductionOperator::Invalid;
332 }
333 llvm_unreachable("Reduction op token kind not caught by 'default'?");
334}
335
336/// Used for cases where we expect an identifier-like token, but don't want to
337/// give awkward error messages in cases where it is accidentially a keyword.
338bool expectIdentifierOrKeyword(Parser &P) {
339 Token Tok = P.getCurToken();
340
341 if (isTokenIdentifierOrKeyword(P, Tok))
342 return false;
343
344 P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
345 return true;
346}
347
348OpenACCDirectiveKind
349ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
350 OpenACCDirectiveKindEx ExtDirKind) {
351 Token SecondTok = P.getCurToken();
352
353 if (SecondTok.isAnnotation()) {
354 P.Diag(FirstTok, diag::err_acc_invalid_directive)
355 << 0 << FirstTok.getIdentifierInfo();
356 return OpenACCDirectiveKind::Invalid;
357 }
358
359 // Consume the second name anyway, this way we can continue on without making
360 // this oddly look like a clause.
361 P.ConsumeAnyToken();
362
363 if (!isOpenACCDirectiveKind(Kind: OpenACCDirectiveKind::Data, Tok: SecondTok)) {
364 if (!SecondTok.is(tok::identifier))
365 P.Diag(SecondTok, diag::err_expected) << tok::identifier;
366 else
367 P.Diag(FirstTok, diag::err_acc_invalid_directive)
368 << 1 << FirstTok.getIdentifierInfo()->getName()
369 << SecondTok.getIdentifierInfo()->getName();
370 return OpenACCDirectiveKind::Invalid;
371 }
372
373 return ExtDirKind == OpenACCDirectiveKindEx::Enter
374 ? OpenACCDirectiveKind::EnterData
375 : OpenACCDirectiveKind::ExitData;
376}
377
378OpenACCAtomicKind ParseOpenACCAtomicKind(Parser &P) {
379 Token AtomicClauseToken = P.getCurToken();
380
381 // #pragma acc atomic is equivilent to update:
382 if (AtomicClauseToken.isAnnotation())
383 return OpenACCAtomicKind::Update;
384
385 OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(Tok: AtomicClauseToken);
386
387 // If we don't know what this is, treat it as 'nothing', and treat the rest of
388 // this as a clause list, which, despite being invalid, is likely what the
389 // user was trying to do.
390 if (AtomicKind == OpenACCAtomicKind::Invalid)
391 return OpenACCAtomicKind::Update;
392
393 P.ConsumeToken();
394 return AtomicKind;
395}
396
397// Parse and consume the tokens for OpenACC Directive/Construct kinds.
398OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
399 Token FirstTok = P.getCurToken();
400
401 // Just #pragma acc can get us immediately to the end, make sure we don't
402 // introspect on the spelling before then.
403 if (FirstTok.isNot(K: tok::identifier)) {
404 P.Diag(FirstTok, diag::err_acc_missing_directive);
405
406 if (P.getCurToken().isNot(K: tok::annot_pragma_openacc_end))
407 P.ConsumeAnyToken();
408
409 return OpenACCDirectiveKind::Invalid;
410 }
411
412 P.ConsumeToken();
413
414 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(Tok: FirstTok);
415
416 // OpenACCDirectiveKindEx is meant to be an extended list
417 // over OpenACCDirectiveKind, so any value below Invalid is one of the
418 // OpenACCDirectiveKind values. This switch takes care of all of the extra
419 // parsing required for the Extended values. At the end of this block,
420 // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can
421 // immediately cast it and use it as that.
422 if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) {
423 switch (ExDirKind) {
424 case OpenACCDirectiveKindEx::Invalid: {
425 P.Diag(FirstTok, diag::err_acc_invalid_directive)
426 << 0 << FirstTok.getIdentifierInfo();
427 return OpenACCDirectiveKind::Invalid;
428 }
429 case OpenACCDirectiveKindEx::Enter:
430 case OpenACCDirectiveKindEx::Exit:
431 return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExtDirKind: ExDirKind);
432 }
433 }
434
435 OpenACCDirectiveKind DirKind = static_cast<OpenACCDirectiveKind>(ExDirKind);
436
437 // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any
438 // other attempt at a combined construct will be diagnosed as an invalid
439 // clause.
440 Token SecondTok = P.getCurToken();
441 if (!SecondTok.isAnnotation() &&
442 isOpenACCDirectiveKind(Kind: OpenACCDirectiveKind::Loop, Tok: SecondTok)) {
443 switch (DirKind) {
444 default:
445 // Nothing to do except in the below cases, as they should be diagnosed as
446 // a clause.
447 break;
448 case OpenACCDirectiveKind::Parallel:
449 P.ConsumeToken();
450 return OpenACCDirectiveKind::ParallelLoop;
451 case OpenACCDirectiveKind::Serial:
452 P.ConsumeToken();
453 return OpenACCDirectiveKind::SerialLoop;
454 case OpenACCDirectiveKind::Kernels:
455 P.ConsumeToken();
456 return OpenACCDirectiveKind::KernelsLoop;
457 }
458 }
459
460 return DirKind;
461}
462
463enum ClauseParensKind {
464 None,
465 Optional,
466 Required
467};
468
469ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
470 OpenACCClauseKind Kind) {
471 switch (Kind) {
472 case OpenACCClauseKind::Self:
473 return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required
474 : ClauseParensKind::Optional;
475 case OpenACCClauseKind::Async:
476 case OpenACCClauseKind::Worker:
477 case OpenACCClauseKind::Vector:
478 case OpenACCClauseKind::Gang:
479 case OpenACCClauseKind::Wait:
480 return ClauseParensKind::Optional;
481
482 case OpenACCClauseKind::Default:
483 case OpenACCClauseKind::If:
484 case OpenACCClauseKind::Create:
485 case OpenACCClauseKind::Copy:
486 case OpenACCClauseKind::CopyIn:
487 case OpenACCClauseKind::CopyOut:
488 case OpenACCClauseKind::UseDevice:
489 case OpenACCClauseKind::NoCreate:
490 case OpenACCClauseKind::Present:
491 case OpenACCClauseKind::DevicePtr:
492 case OpenACCClauseKind::Attach:
493 case OpenACCClauseKind::Detach:
494 case OpenACCClauseKind::Private:
495 case OpenACCClauseKind::FirstPrivate:
496 case OpenACCClauseKind::Delete:
497 case OpenACCClauseKind::DeviceResident:
498 case OpenACCClauseKind::Device:
499 case OpenACCClauseKind::Link:
500 case OpenACCClauseKind::Host:
501 case OpenACCClauseKind::Reduction:
502 case OpenACCClauseKind::Collapse:
503 case OpenACCClauseKind::Bind:
504 case OpenACCClauseKind::VectorLength:
505 case OpenACCClauseKind::NumGangs:
506 case OpenACCClauseKind::NumWorkers:
507 case OpenACCClauseKind::DeviceNum:
508 case OpenACCClauseKind::DefaultAsync:
509 case OpenACCClauseKind::DeviceType:
510 case OpenACCClauseKind::DType:
511 case OpenACCClauseKind::Tile:
512 return ClauseParensKind::Required;
513
514 case OpenACCClauseKind::Auto:
515 case OpenACCClauseKind::Finalize:
516 case OpenACCClauseKind::IfPresent:
517 case OpenACCClauseKind::Independent:
518 case OpenACCClauseKind::Invalid:
519 case OpenACCClauseKind::NoHost:
520 case OpenACCClauseKind::Seq:
521 return ClauseParensKind::None;
522 }
523 llvm_unreachable("Unhandled clause kind");
524}
525
526bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind,
527 OpenACCClauseKind Kind) {
528 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
529}
530
531bool ClauseHasRequiredParens(OpenACCDirectiveKind DirKind,
532 OpenACCClauseKind Kind) {
533 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required;
534}
535
536ExprResult ParseOpenACCConditionalExpr(Parser &P) {
537 // FIXME: It isn't clear if the spec saying 'condition' means the same as
538 // it does in an if/while/etc (See ParseCXXCondition), however as it was
539 // written with Fortran/C in mind, we're going to assume it just means an
540 // 'expression evaluating to boolean'.
541 return P.getActions().CorrectDelayedTyposInExpr(ER: P.ParseExpression());
542}
543
544// Skip until we see the end of pragma token, but don't consume it. This is us
545// just giving up on the rest of the pragma so we can continue executing. We
546// have to do this because 'SkipUntil' considers paren balancing, which isn't
547// what we want.
548void SkipUntilEndOfDirective(Parser &P) {
549 while (P.getCurToken().isNot(K: tok::annot_pragma_openacc_end))
550 P.ConsumeAnyToken();
551}
552
553} // namespace
554
555// OpenACC 3.3, section 1.7:
556// To simplify the specification and convey appropriate constraint information,
557// a pqr-list is a comma-separated list of pdr items. The one exception is a
558// clause-list, which is a list of one or more clauses optionally separated by
559// commas.
560void Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
561 bool FirstClause = true;
562 while (getCurToken().isNot(K: tok::annot_pragma_openacc_end)) {
563 // Comma is optional in a clause-list.
564 if (!FirstClause && getCurToken().is(K: tok::comma))
565 ConsumeToken();
566 FirstClause = false;
567
568 // Recovering from a bad clause is really difficult, so we just give up on
569 // error.
570 if (ParseOpenACCClause(DirKind)) {
571 SkipUntilEndOfDirective(P&: *this);
572 return;
573 }
574 }
575}
576
577ExprResult Parser::ParseOpenACCIntExpr() {
578 // FIXME: this is required to be an integer expression (or dependent), so we
579 // should ensure that is the case by passing this to SEMA here.
580 return getActions().CorrectDelayedTyposInExpr(ER: ParseAssignmentExpression());
581}
582
583bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) {
584 // FIXME: Future clauses will require 'special word' parsing, check for one,
585 // then parse it based on whether it is a clause that requires a 'special
586 // word'.
587 (void)Kind;
588
589 // If the var parsing fails, skip until the end of the directive as this is
590 // an expression and gets messy if we try to continue otherwise.
591 if (ParseOpenACCVar())
592 return true;
593
594 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
595 ExpectAndConsume(ExpectedTok: tok::comma);
596
597 // If the var parsing fails, skip until the end of the directive as this is
598 // an expression and gets messy if we try to continue otherwise.
599 if (ParseOpenACCVar())
600 return true;
601 }
602 return false;
603}
604
605/// OpenACC 3.3 Section 2.4:
606/// The argument to the device_type clause is a comma-separated list of one or
607/// more device architecture name identifiers, or an asterisk.
608///
609/// The syntax of the device_type clause is
610/// device_type( * )
611/// device_type( device-type-list )
612///
613/// The device_type clause may be abbreviated to dtype.
614bool Parser::ParseOpenACCDeviceTypeList() {
615
616 if (expectIdentifierOrKeyword(P&: *this)) {
617 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
618 Flags: Parser::StopBeforeMatch);
619 return false;
620 }
621 ConsumeToken();
622
623 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
624 ExpectAndConsume(ExpectedTok: tok::comma);
625
626 if (expectIdentifierOrKeyword(P&: *this)) {
627 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
628 Flags: Parser::StopBeforeMatch);
629 return false;
630 }
631 ConsumeToken();
632 }
633 return false;
634}
635
636/// OpenACC 3.3 Section 2.9:
637/// size-expr is one of:
638// *
639// int-expr
640// Note that this is specified under 'gang-arg-list', but also applies to 'tile'
641// via reference.
642bool Parser::ParseOpenACCSizeExpr() {
643 // FIXME: Ensure these are constant expressions.
644
645 // The size-expr ends up being ambiguous when only looking at the current
646 // token, as it could be a deref of a variable/expression.
647 if (getCurToken().is(K: tok::star) &&
648 NextToken().isOneOf(K1: tok::comma, Ks: tok::r_paren,
649 Ks: tok::annot_pragma_openacc_end)) {
650 ConsumeToken();
651 return false;
652 }
653
654 return getActions()
655 .CorrectDelayedTyposInExpr(ER: ParseAssignmentExpression())
656 .isInvalid();
657}
658
659bool Parser::ParseOpenACCSizeExprList() {
660 if (ParseOpenACCSizeExpr()) {
661 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
662 Flags: Parser::StopBeforeMatch);
663 return false;
664 }
665
666 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
667 ExpectAndConsume(ExpectedTok: tok::comma);
668
669 if (ParseOpenACCSizeExpr()) {
670 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
671 Flags: Parser::StopBeforeMatch);
672 return false;
673 }
674 }
675 return false;
676}
677
678/// OpenACC 3.3 Section 2.9:
679///
680/// where gang-arg is one of:
681/// [num:]int-expr
682/// dim:int-expr
683/// static:size-expr
684bool Parser::ParseOpenACCGangArg() {
685
686 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::Static, Tok: getCurToken()) &&
687 NextToken().is(K: tok::colon)) {
688 // 'static' just takes a size-expr, which is an int-expr or an asterisk.
689 ConsumeToken();
690 ConsumeToken();
691 return ParseOpenACCSizeExpr();
692 }
693
694 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::Dim, Tok: getCurToken()) &&
695 NextToken().is(K: tok::colon)) {
696 ConsumeToken();
697 ConsumeToken();
698 return ParseOpenACCIntExpr().isInvalid();
699 }
700
701 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::Num, Tok: getCurToken()) &&
702 NextToken().is(K: tok::colon)) {
703 ConsumeToken();
704 ConsumeToken();
705 // Fallthrough to the 'int-expr' handling for when 'num' is omitted.
706 }
707 // This is just the 'num' case where 'num' is optional.
708 return ParseOpenACCIntExpr().isInvalid();
709}
710
711bool Parser::ParseOpenACCGangArgList() {
712 if (ParseOpenACCGangArg()) {
713 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
714 Flags: Parser::StopBeforeMatch);
715 return false;
716 }
717
718 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
719 ExpectAndConsume(ExpectedTok: tok::comma);
720
721 if (ParseOpenACCGangArg()) {
722 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end,
723 Flags: Parser::StopBeforeMatch);
724 return false;
725 }
726 }
727 return false;
728}
729
730// The OpenACC Clause List is a comma or space-delimited list of clauses (see
731// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't
732// really have its owner grammar and each individual one has its own definition.
733// However, they all are named with a single-identifier (or auto/default!)
734// token, followed in some cases by either braces or parens.
735bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) {
736 // A number of clause names are actually keywords, so accept a keyword that
737 // can be converted to a name.
738 if (expectIdentifierOrKeyword(P&: *this))
739 return true;
740
741 OpenACCClauseKind Kind = getOpenACCClauseKind(Tok: getCurToken());
742
743 if (Kind == OpenACCClauseKind::Invalid)
744 return Diag(getCurToken(), diag::err_acc_invalid_clause)
745 << getCurToken().getIdentifierInfo();
746
747 // Consume the clause name.
748 ConsumeToken();
749
750 return ParseOpenACCClauseParams(DirKind, Kind);
751}
752
753bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
754 OpenACCClauseKind Kind) {
755 BalancedDelimiterTracker Parens(*this, tok::l_paren,
756 tok::annot_pragma_openacc_end);
757
758 if (ClauseHasRequiredParens(DirKind, Kind)) {
759 if (Parens.expectAndConsume()) {
760 // We are missing a paren, so assume that the person just forgot the
761 // parameter. Return 'false' so we try to continue on and parse the next
762 // clause.
763 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openacc_end,
764 Flags: Parser::StopBeforeMatch);
765 return false;
766 }
767
768 switch (Kind) {
769 case OpenACCClauseKind::Default: {
770 Token DefKindTok = getCurToken();
771
772 if (expectIdentifierOrKeyword(P&: *this))
773 break;
774
775 ConsumeToken();
776
777 if (getOpenACCDefaultClauseKind(DefKindTok) ==
778 OpenACCDefaultClauseKind::Invalid)
779 Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
780
781 break;
782 }
783 case OpenACCClauseKind::If: {
784 ExprResult CondExpr = ParseOpenACCConditionalExpr(P&: *this);
785 // An invalid expression can be just about anything, so just give up on
786 // this clause list.
787 if (CondExpr.isInvalid()) {
788 Parens.skipToEnd();
789 return false;
790 }
791 break;
792 }
793 case OpenACCClauseKind::CopyIn:
794 tryParseAndConsumeSpecialTokenKind(
795 P&: *this, Kind: OpenACCSpecialTokenKind::ReadOnly, DirOrClause: Kind);
796 if (ParseOpenACCClauseVarList(Kind)) {
797 Parens.skipToEnd();
798 return false;
799 }
800 break;
801 case OpenACCClauseKind::Create:
802 case OpenACCClauseKind::CopyOut:
803 tryParseAndConsumeSpecialTokenKind(P&: *this, Kind: OpenACCSpecialTokenKind::Zero,
804 DirOrClause: Kind);
805 if (ParseOpenACCClauseVarList(Kind)) {
806 Parens.skipToEnd();
807 return false;
808 }
809 break;
810 case OpenACCClauseKind::Reduction:
811 // If we're missing a clause-kind (or it is invalid), see if we can parse
812 // the var-list anyway.
813 ParseReductionOperator(P&: *this);
814 if (ParseOpenACCClauseVarList(Kind)) {
815 Parens.skipToEnd();
816 return false;
817 }
818 break;
819 case OpenACCClauseKind::Self:
820 // The 'self' clause is a var-list instead of a 'condition' in the case of
821 // the 'update' clause, so we have to handle it here. U se an assert to
822 // make sure we get the right differentiator.
823 assert(DirKind == OpenACCDirectiveKind::Update);
824 LLVM_FALLTHROUGH;
825 case OpenACCClauseKind::Attach:
826 case OpenACCClauseKind::Copy:
827 case OpenACCClauseKind::Delete:
828 case OpenACCClauseKind::Detach:
829 case OpenACCClauseKind::Device:
830 case OpenACCClauseKind::DeviceResident:
831 case OpenACCClauseKind::DevicePtr:
832 case OpenACCClauseKind::FirstPrivate:
833 case OpenACCClauseKind::Host:
834 case OpenACCClauseKind::Link:
835 case OpenACCClauseKind::NoCreate:
836 case OpenACCClauseKind::Present:
837 case OpenACCClauseKind::Private:
838 case OpenACCClauseKind::UseDevice:
839 if (ParseOpenACCClauseVarList(Kind)) {
840 Parens.skipToEnd();
841 return false;
842 }
843 break;
844 case OpenACCClauseKind::Collapse: {
845 tryParseAndConsumeSpecialTokenKind(P&: *this, Kind: OpenACCSpecialTokenKind::Force,
846 DirOrClause: Kind);
847 ExprResult NumLoops =
848 getActions().CorrectDelayedTyposInExpr(ER: ParseConstantExpression());
849 if (NumLoops.isInvalid()) {
850 Parens.skipToEnd();
851 return false;
852 }
853 break;
854 }
855 case OpenACCClauseKind::Bind: {
856 ExprResult BindArg = ParseOpenACCBindClauseArgument();
857 if (BindArg.isInvalid()) {
858 Parens.skipToEnd();
859 return false;
860 }
861 break;
862 }
863 case OpenACCClauseKind::NumGangs:
864 case OpenACCClauseKind::NumWorkers:
865 case OpenACCClauseKind::DeviceNum:
866 case OpenACCClauseKind::DefaultAsync:
867 case OpenACCClauseKind::VectorLength: {
868 ExprResult IntExpr = ParseOpenACCIntExpr();
869 if (IntExpr.isInvalid()) {
870 Parens.skipToEnd();
871 return false;
872 }
873 break;
874 }
875 case OpenACCClauseKind::DType:
876 case OpenACCClauseKind::DeviceType:
877 if (getCurToken().is(K: tok::star)) {
878 // FIXME: We want to mark that this is an 'everything else' type of
879 // device_type in Sema.
880 ConsumeToken();
881 } else if (ParseOpenACCDeviceTypeList()) {
882 Parens.skipToEnd();
883 return false;
884 }
885 break;
886 case OpenACCClauseKind::Tile:
887 if (ParseOpenACCSizeExprList()) {
888 Parens.skipToEnd();
889 return false;
890 }
891 break;
892 default:
893 llvm_unreachable("Not a required parens type?");
894 }
895
896 return Parens.consumeClose();
897 } else if (ClauseHasOptionalParens(DirKind, Kind)) {
898 if (!Parens.consumeOpen()) {
899 switch (Kind) {
900 case OpenACCClauseKind::Self: {
901 assert(DirKind != OpenACCDirectiveKind::Update);
902 ExprResult CondExpr = ParseOpenACCConditionalExpr(P&: *this);
903 // An invalid expression can be just about anything, so just give up on
904 // this clause list.
905 if (CondExpr.isInvalid()) {
906 Parens.skipToEnd();
907 return false;
908 }
909 break;
910 }
911 case OpenACCClauseKind::Vector:
912 case OpenACCClauseKind::Worker: {
913 tryParseAndConsumeSpecialTokenKind(P&: *this,
914 Kind: Kind == OpenACCClauseKind::Vector
915 ? OpenACCSpecialTokenKind::Length
916 : OpenACCSpecialTokenKind::Num,
917 DirOrClause: Kind);
918 ExprResult IntExpr = ParseOpenACCIntExpr();
919 if (IntExpr.isInvalid()) {
920 Parens.skipToEnd();
921 return false;
922 }
923 break;
924 }
925 case OpenACCClauseKind::Async: {
926 ExprResult AsyncArg = ParseOpenACCAsyncArgument();
927 if (AsyncArg.isInvalid()) {
928 Parens.skipToEnd();
929 return false;
930 }
931 break;
932 }
933 case OpenACCClauseKind::Gang:
934 if (ParseOpenACCGangArgList()) {
935 Parens.skipToEnd();
936 return false;
937 }
938 break;
939 case OpenACCClauseKind::Wait:
940 if (ParseOpenACCWaitArgument()) {
941 Parens.skipToEnd();
942 return false;
943 }
944 break;
945 default:
946 llvm_unreachable("Not an optional parens type?");
947 }
948 Parens.consumeClose();
949 }
950 }
951 return false;
952}
953
954/// OpenACC 3.3 section 2.16:
955/// In this section and throughout the specification, the term async-argument
956/// means a nonnegative scalar integer expression (int for C or C++, integer for
957/// Fortran), or one of the special values acc_async_noval or acc_async_sync, as
958/// defined in the C header file and the Fortran openacc module. The special
959/// values are negative values, so as not to conflict with a user-specified
960/// nonnegative async-argument.
961ExprResult Parser::ParseOpenACCAsyncArgument() {
962 return getActions().CorrectDelayedTyposInExpr(ER: ParseAssignmentExpression());
963}
964
965/// OpenACC 3.3, section 2.16:
966/// In this section and throughout the specification, the term wait-argument
967/// means:
968/// [ devnum : int-expr : ] [ queues : ] async-argument-list
969bool Parser::ParseOpenACCWaitArgument() {
970 // [devnum : int-expr : ]
971 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::DevNum, Tok) &&
972 NextToken().is(K: tok::colon)) {
973 // Consume devnum.
974 ConsumeToken();
975 // Consume colon.
976 ConsumeToken();
977
978 ExprResult IntExpr = ParseOpenACCIntExpr();
979 if (IntExpr.isInvalid())
980 return true;
981
982 if (ExpectAndConsume(ExpectedTok: tok::colon))
983 return true;
984 }
985
986 // [ queues : ]
987 if (isOpenACCSpecialToken(Kind: OpenACCSpecialTokenKind::Queues, Tok) &&
988 NextToken().is(K: tok::colon)) {
989 // Consume queues.
990 ConsumeToken();
991 // Consume colon.
992 ConsumeToken();
993 }
994
995 // OpenACC 3.3, section 2.16:
996 // the term 'async-argument' means a nonnegative scalar integer expression, or
997 // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined
998 // in the C header file and the Fortran opacc module.
999 bool FirstArg = true;
1000 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
1001 if (!FirstArg) {
1002 if (ExpectAndConsume(ExpectedTok: tok::comma))
1003 return true;
1004 }
1005 FirstArg = false;
1006
1007 ExprResult CurArg = ParseOpenACCAsyncArgument();
1008
1009 if (CurArg.isInvalid())
1010 return true;
1011 }
1012
1013 return false;
1014}
1015
1016ExprResult Parser::ParseOpenACCIDExpression() {
1017 ExprResult Res;
1018 if (getLangOpts().CPlusPlus) {
1019 Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true);
1020 } else {
1021 // There isn't anything quite the same as ParseCXXIdExpression for C, so we
1022 // need to get the identifier, then call into Sema ourselves.
1023
1024 if (Tok.isNot(K: tok::identifier)) {
1025 Diag(Tok, diag::err_expected) << tok::identifier;
1026 return ExprError();
1027 }
1028
1029 Token FuncName = getCurToken();
1030 UnqualifiedId Name;
1031 CXXScopeSpec ScopeSpec;
1032 SourceLocation TemplateKWLoc;
1033 Name.setIdentifier(Id: FuncName.getIdentifierInfo(), IdLoc: ConsumeToken());
1034
1035 // Ensure this is a valid identifier. We don't accept causing implicit
1036 // function declarations per the spec, so always claim to not have trailing
1037 // L Paren.
1038 Res = Actions.ActOnIdExpression(S: getCurScope(), SS&: ScopeSpec, TemplateKWLoc,
1039 Id&: Name, /*HasTrailingLParen=*/false,
1040 /*isAddressOfOperand=*/IsAddressOfOperand: false);
1041 }
1042
1043 return getActions().CorrectDelayedTyposInExpr(ER: Res);
1044}
1045
1046ExprResult Parser::ParseOpenACCBindClauseArgument() {
1047 // OpenACC 3.3 section 2.15:
1048 // The bind clause specifies the name to use when calling the procedure on a
1049 // device other than the host. If the name is specified as an identifier, it
1050 // is called as if that name were specified in the language being compiled. If
1051 // the name is specified as a string, the string is used for the procedure
1052 // name unmodified.
1053 if (getCurToken().is(K: tok::r_paren)) {
1054 Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
1055 return ExprError();
1056 }
1057
1058 if (tok::isStringLiteral(K: getCurToken().getKind()))
1059 return getActions().CorrectDelayedTyposInExpr(ER: ParseStringLiteralExpression(
1060 /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
1061
1062 return ParseOpenACCIDExpression();
1063}
1064
1065/// OpenACC 3.3, section 1.6:
1066/// In this spec, a 'var' (in italics) is one of the following:
1067/// - a variable name (a scalar, array, or compisite variable name)
1068/// - a subarray specification with subscript ranges
1069/// - an array element
1070/// - a member of a composite variable
1071/// - a common block name between slashes (fortran only)
1072bool Parser::ParseOpenACCVar() {
1073 OpenACCArraySectionRAII ArraySections(*this);
1074 ExprResult Res =
1075 getActions().CorrectDelayedTyposInExpr(ER: ParseAssignmentExpression());
1076 return Res.isInvalid();
1077}
1078
1079/// OpenACC 3.3, section 2.10:
1080/// In C and C++, the syntax of the cache directive is:
1081///
1082/// #pragma acc cache ([readonly:]var-list) new-line
1083void Parser::ParseOpenACCCacheVarList() {
1084 // If this is the end of the line, just return 'false' and count on the close
1085 // paren diagnostic to catch the issue.
1086 if (getCurToken().isAnnotation())
1087 return;
1088
1089 // The VarList is an optional `readonly:` followed by a list of a variable
1090 // specifications. Consume something that looks like a 'tag', and diagnose if
1091 // it isn't 'readonly'.
1092 if (tryParseAndConsumeSpecialTokenKind(P&: *this,
1093 Kind: OpenACCSpecialTokenKind::ReadOnly,
1094 DirOrClause: OpenACCDirectiveKind::Cache)) {
1095 // FIXME: Record that this is a 'readonly' so that we can use that during
1096 // Sema/AST generation.
1097 }
1098
1099 bool FirstArray = true;
1100 while (!getCurToken().isOneOf(K1: tok::r_paren, K2: tok::annot_pragma_openacc_end)) {
1101 if (!FirstArray)
1102 ExpectAndConsume(ExpectedTok: tok::comma);
1103 FirstArray = false;
1104
1105 // OpenACC 3.3, section 2.10:
1106 // A 'var' in a cache directive must be a single array element or a simple
1107 // subarray. In C and C++, a simple subarray is an array name followed by
1108 // an extended array range specification in brackets, with a start and
1109 // length such as:
1110 //
1111 // arr[lower:length]
1112 //
1113 if (ParseOpenACCVar())
1114 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openacc_end, T3: tok::comma,
1115 Flags: StopBeforeMatch);
1116 }
1117}
1118
1119void Parser::ParseOpenACCDirective() {
1120 OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(P&: *this);
1121
1122 // Once we've parsed the construct/directive name, some have additional
1123 // specifiers that need to be taken care of. Atomic has an 'atomic-clause'
1124 // that needs to be parsed.
1125 if (DirKind == OpenACCDirectiveKind::Atomic)
1126 ParseOpenACCAtomicKind(P&: *this);
1127
1128 // We've successfully parsed the construct/directive name, however a few of
1129 // the constructs have optional parens that contain further details.
1130 BalancedDelimiterTracker T(*this, tok::l_paren,
1131 tok::annot_pragma_openacc_end);
1132
1133 if (!T.consumeOpen()) {
1134 switch (DirKind) {
1135 default:
1136 Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren);
1137 T.skipToEnd();
1138 break;
1139 case OpenACCDirectiveKind::Routine: {
1140 // Routine has an optional paren-wrapped name of a function in the local
1141 // scope. We parse the name, emitting any diagnostics
1142 ExprResult RoutineName = ParseOpenACCIDExpression();
1143 // If the routine name is invalid, just skip until the closing paren to
1144 // recover more gracefully.
1145 if (RoutineName.isInvalid())
1146 T.skipToEnd();
1147 else
1148 T.consumeClose();
1149 break;
1150 }
1151 case OpenACCDirectiveKind::Cache:
1152 ParseOpenACCCacheVarList();
1153 // The ParseOpenACCCacheVarList function manages to recover from failures,
1154 // so we can always consume the close.
1155 T.consumeClose();
1156 break;
1157 case OpenACCDirectiveKind::Wait:
1158 // OpenACC has an optional paren-wrapped 'wait-argument'.
1159 if (ParseOpenACCWaitArgument())
1160 T.skipToEnd();
1161 else
1162 T.consumeClose();
1163 break;
1164 }
1165 } else if (DirKind == OpenACCDirectiveKind::Cache) {
1166 // Cache's paren var-list is required, so error here if it isn't provided.
1167 // We know that the consumeOpen above left the first non-paren here, so
1168 // diagnose, then continue as if it was completely omitted.
1169 Diag(Tok, diag::err_expected) << tok::l_paren;
1170 }
1171
1172 // Parses the list of clauses, if present.
1173 ParseOpenACCClauseList(DirKind);
1174
1175 Diag(getCurToken(), diag::warn_pragma_acc_unimplemented);
1176 assert(Tok.is(tok::annot_pragma_openacc_end) &&
1177 "Didn't parse all OpenACC Clauses");
1178 ConsumeAnnotationToken();
1179}
1180
1181// Parse OpenACC directive on a declaration.
1182Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() {
1183 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1184
1185 ParsingOpenACCDirectiveRAII DirScope(*this);
1186 ConsumeAnnotationToken();
1187
1188 ParseOpenACCDirective();
1189
1190 return nullptr;
1191}
1192
1193// Parse OpenACC Directive on a Statement.
1194StmtResult Parser::ParseOpenACCDirectiveStmt() {
1195 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1196
1197 ParsingOpenACCDirectiveRAII DirScope(*this);
1198 ConsumeAnnotationToken();
1199
1200 ParseOpenACCDirective();
1201
1202 return StmtEmpty();
1203}
1204

source code of clang/lib/Parse/ParseOpenACC.cpp