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