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