Skip to content

Commit df3db03

Browse files
authored
[OpenACC] Implement 'wait' construct parsing (#74752)
The 'wait' construct comes in two forms: one with no parens, the second with a 'wait-argument'. This implements both forms for constructs. Additionally, the 'wait-argument' parsing is split into its own function because the 'wait clause' can also take the same 'wait-argument'.
1 parent 2cd43e9 commit df3db03

File tree

4 files changed

+248
-1
lines changed

4 files changed

+248
-1
lines changed

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ enum class OpenACCDirectiveKind {
5353
Shutdown,
5454
Set,
5555
Update,
56-
// FIXME: wait construct.
56+
Wait,
5757

5858
// Procedure Calls in Compute Regions.
5959
Routine,

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3544,6 +3544,7 @@ class Parser : public CodeCompletionHandler {
35443544
void ParseOpenACCCacheVarList();
35453545
/// Parses a single variable in a variable list for the 'cache' construct.
35463546
bool ParseOpenACCCacheVar();
3547+
bool ParseOpenACCWaitArgument();
35473548

35483549
private:
35493550
//===--------------------------------------------------------------------===//

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {
5656
.Case("shutdown", OpenACCDirectiveKind::Shutdown)
5757
.Case("set", OpenACCDirectiveKind::Shutdown)
5858
.Case("update", OpenACCDirectiveKind::Update)
59+
.Case("wait", OpenACCDirectiveKind::Wait)
5960
.Default(OpenACCDirectiveKind::Invalid);
6061

6162
if (DirKind != OpenACCDirectiveKind::Invalid)
@@ -82,6 +83,24 @@ OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
8283
.Default(OpenACCAtomicKind::Invalid);
8384
}
8485

86+
enum class OpenACCSpecialTokenKind {
87+
DevNum,
88+
Queues,
89+
};
90+
91+
bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {
92+
if (!Tok.is(tok::identifier))
93+
return false;
94+
95+
switch (Kind) {
96+
case OpenACCSpecialTokenKind::DevNum:
97+
return Tok.getIdentifierInfo()->isStr("devnum");
98+
case OpenACCSpecialTokenKind::Queues:
99+
return Tok.getIdentifierInfo()->isStr("queues");
100+
}
101+
llvm_unreachable("Unknown 'Kind' Passed");
102+
}
103+
85104
bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
86105
if (!Tok.is(tok::identifier))
87106
return false;
@@ -123,6 +142,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
123142
return Tok.getIdentifierInfo()->isStr("set");
124143
case OpenACCDirectiveKind::Update:
125144
return Tok.getIdentifierInfo()->isStr("update");
145+
case OpenACCDirectiveKind::Wait:
146+
return Tok.getIdentifierInfo()->isStr("wait");
126147
case OpenACCDirectiveKind::Invalid:
127148
return false;
128149
}
@@ -251,6 +272,67 @@ void ParseOpenACCClauseList(Parser &P) {
251272

252273
} // namespace
253274

275+
/// OpenACC 3.3, section 2.16:
276+
/// In this section and throughout the specification, the term wait-argument
277+
/// means:
278+
/// [ devnum : int-expr : ] [ queues : ] async-argument-list
279+
bool Parser::ParseOpenACCWaitArgument() {
280+
// [devnum : int-expr : ]
281+
if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
282+
NextToken().is(tok::colon)) {
283+
// Consume devnum.
284+
ConsumeToken();
285+
// Consume colon.
286+
ConsumeToken();
287+
288+
ExprResult IntExpr =
289+
getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
290+
if (IntExpr.isInvalid())
291+
return true;
292+
293+
if (ExpectAndConsume(tok::colon))
294+
return true;
295+
}
296+
297+
// [ queues : ]
298+
if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
299+
NextToken().is(tok::colon)) {
300+
// Consume queues.
301+
ConsumeToken();
302+
// Consume colon.
303+
ConsumeToken();
304+
}
305+
306+
// OpenACC 3.3, section 2.16:
307+
// the term 'async-argument' means a nonnegative scalar integer expression, or
308+
// one of the special values 'acc_async_noval' or 'acc_async_sync', as defined
309+
// in the C header file and the Fortran opacc module.
310+
//
311+
// We are parsing this simply as list of assignment expressions (to avoid
312+
// comma being troublesome), and will ensure it is an integral type. The
313+
// 'special' types are defined as macros, so we can't really check those
314+
// (other than perhaps as values at one point?), but the standard does say it
315+
// is implementation-defined to use any other negative value.
316+
//
317+
//
318+
bool FirstArg = true;
319+
while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
320+
if (!FirstArg) {
321+
if (ExpectAndConsume(tok::comma))
322+
return true;
323+
}
324+
FirstArg = false;
325+
326+
ExprResult CurArg =
327+
getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
328+
329+
if (CurArg.isInvalid())
330+
return true;
331+
}
332+
333+
return false;
334+
}
335+
254336
ExprResult Parser::ParseOpenACCIDExpression() {
255337
ExprResult Res;
256338
if (getLangOpts().CPlusPlus) {
@@ -399,6 +481,13 @@ void Parser::ParseOpenACCDirective() {
399481
// so we can always consume the close.
400482
T.consumeClose();
401483
break;
484+
case OpenACCDirectiveKind::Wait:
485+
// OpenACC has an optional paren-wrapped 'wait-argument'.
486+
if (ParseOpenACCWaitArgument())
487+
T.skipToEnd();
488+
else
489+
T.consumeClose();
490+
break;
402491
}
403492
} else if (DirKind == OpenACCDirectiveKind::Cache) {
404493
// Cache's paren var-list is required, so error here if it isn't provided.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// RUN: %clang_cc1 %s -verify -fopenacc
2+
3+
void func() {
4+
int i, j;
5+
6+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
7+
#pragma acc wait
8+
9+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
10+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
11+
#pragma acc wait clause-list
12+
13+
// expected-error@+3{{expected ')'}}
14+
// expected-note@+2{{to match this '('}}
15+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
16+
#pragma acc wait (
17+
18+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
19+
#pragma acc wait ()
20+
21+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
22+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
23+
#pragma acc wait () clause-list
24+
25+
// expected-error@+4{{expected expression}}
26+
// expected-error@+3{{expected ')'}}
27+
// expected-note@+2{{to match this '('}}
28+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
29+
#pragma acc wait (devnum:
30+
31+
// expected-error@+2{{expected expression}}
32+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
33+
#pragma acc wait (devnum:)
34+
35+
// expected-error@+3{{expected expression}}
36+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
37+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
38+
#pragma acc wait (devnum:) clause-list
39+
40+
// expected-error@+4{{expected ':'}}
41+
// expected-error@+3{{expected ')'}}
42+
// expected-note@+2{{to match this '('}}
43+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
44+
#pragma acc wait (devnum: i + j
45+
46+
// expected-error@+2{{expected ':'}}
47+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
48+
#pragma acc wait (devnum: i + j)
49+
50+
// expected-error@+3{{expected ':'}}
51+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
52+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
53+
#pragma acc wait (devnum: i + j) clause-list
54+
55+
// expected-error@+3{{expected ')'}}
56+
// expected-note@+2{{to match this '('}}
57+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
58+
#pragma acc wait (queues:
59+
60+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
61+
#pragma acc wait (queues:)
62+
63+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
64+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
65+
#pragma acc wait (queues:) clause-list
66+
67+
// expected-error@+3{{expected ')'}}
68+
// expected-note@+2{{to match this '('}}
69+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
70+
#pragma acc wait (devnum: i + j:queues:
71+
72+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
73+
#pragma acc wait (devnum: i + j:queues:)
74+
75+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
76+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
77+
#pragma acc wait (devnum: i + j:queues:) clause-list
78+
79+
// expected-error@+4{{use of undeclared identifier 'devnum'}}
80+
// expected-error@+3{{expected ')'}}
81+
// expected-note@+2{{to match this '('}}
82+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
83+
#pragma acc wait (queues:devnum: i + j
84+
85+
// expected-error@+2{{use of undeclared identifier 'devnum'}}
86+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
87+
#pragma acc wait (queues:devnum: i + j)
88+
89+
// expected-error@+3{{use of undeclared identifier 'devnum'}}
90+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
91+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
92+
#pragma acc wait (queues:devnum: i + j) clause-list
93+
94+
// expected-error@+3{{expected ')'}}
95+
// expected-note@+2{{to match this '('}}
96+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
97+
#pragma acc wait(i, j, 1+1, 3.3
98+
99+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
100+
#pragma acc wait(i, j, 1+1, 3.3)
101+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
102+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
103+
#pragma acc wait(i, j, 1+1, 3.3) clause-list
104+
105+
// expected-error@+4{{expected expression}}
106+
// expected-error@+3{{expected ')'}}
107+
// expected-note@+2{{to match this '('}}
108+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
109+
#pragma acc wait(,
110+
111+
// expected-error@+2{{expected expression}}
112+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
113+
#pragma acc wait(,)
114+
115+
// expected-error@+3{{expected expression}}
116+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
117+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
118+
#pragma acc wait(,) clause-list
119+
120+
// expected-error@+3{{expected ')'}}
121+
// expected-note@+2{{to match this '('}}
122+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
123+
#pragma acc wait(queues:i, j, 1+1, 3.3
124+
125+
// expected-error@+4{{expected expression}}
126+
// expected-error@+3{{expected ')'}}
127+
// expected-note@+2{{to match this '('}}
128+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
129+
#pragma acc wait(queues:i, j, 1+1, 3.3,
130+
131+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
132+
#pragma acc wait(queues:i, j, 1+1, 3.3)
133+
134+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
135+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
136+
#pragma acc wait(queues:i, j, 1+1, 3.3) clause-list
137+
138+
// expected-error@+3{{expected ')'}}
139+
// expected-note@+2{{to match this '('}}
140+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
141+
#pragma acc wait(devnum:3:i, j, 1+1, 3.3
142+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
143+
#pragma acc wait(devnum:3:i, j, 1+1, 3.3)
144+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
145+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
146+
#pragma acc wait(devnum:3:i, j, 1+1, 3.3) clause-list
147+
148+
// expected-error@+3{{expected ')'}}
149+
// expected-note@+2{{to match this '('}}
150+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
151+
#pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3
152+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
153+
#pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3)
154+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
155+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
156+
#pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) clause-list
157+
}

0 commit comments

Comments
 (0)