Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp
35234 views
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`.
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.
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.
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
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
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.
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>
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
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
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.
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
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
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.
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
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
548
bool ClauseHasOptionalParens(OpenACCDirectiveKind DirKind,
549
OpenACCClauseKind Kind) {
550
return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
551
}
552
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.
562
void SkipUntilEndOfDirective(Parser &P) {
563
while (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
564
P.ConsumeAnyToken();
565
}
566
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
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
599
Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
600
return {nullptr, OpenACCParseCanContinue::Can};
601
}
602
603
Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
604
return {nullptr, OpenACCParseCanContinue::Cannot};
605
}
606
607
Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {
608
return {Clause, OpenACCParseCanContinue::Can};
609
}
610
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 *>
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
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
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.
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.
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
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
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
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
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
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
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
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
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
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)
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
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
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
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.
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.
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
1468