Skip to content

Commit 0e8b09c

Browse files
authored
[OpenACC] Implement 'default' clause parsing. (#77002)
A simple clause that is permitted on a few different constructs, 'default' takes a required parameter of either 'none' or 'present'. This patch implements parsing for it.
1 parent 1259c05 commit 0e8b09c

File tree

4 files changed

+189
-5
lines changed

4 files changed

+189
-5
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,8 @@ def err_acc_invalid_clause : Error<"invalid OpenACC clause %0">;
13641364
def err_acc_missing_directive : Error<"expected OpenACC directive">;
13651365
def err_acc_invalid_open_paren
13661366
: Error<"expected clause-list or newline in OpenACC directive">;
1367+
def err_acc_invalid_default_clause_kind
1368+
: Error<"invalid value for 'default' clause; expected 'present' or 'none'">;
13671369

13681370
// OpenMP support.
13691371
def warn_pragma_omp_ignored : Warning<

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,21 @@ enum class OpenACCClauseKind {
9090
Vector,
9191
/// 'nohost' clause, allowed on 'routine' directives.
9292
NoHost,
93+
/// 'default' clause, allowed on parallel, serial, kernel (and compound)
94+
/// constructs.
95+
Default,
9396
/// Represents an invalid clause, for the purposes of parsing.
9497
Invalid,
9598
};
99+
100+
enum class OpenACCDefaultClauseKind {
101+
/// 'none' option.
102+
None,
103+
/// 'present' option.
104+
Present,
105+
/// Not a valid option.
106+
Invalid,
107+
};
96108
} // namespace clang
97109

98110
#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,17 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
7676
if (Tok.is(tok::kw_auto))
7777
return OpenACCClauseKind::Auto;
7878

79+
// default is a keyword, so make sure we parse it correctly.
80+
if (Tok.is(tok::kw_default))
81+
return OpenACCClauseKind::Default;
82+
7983
if (!Tok.is(tok::identifier))
8084
return OpenACCClauseKind::Invalid;
8185

8286
return llvm::StringSwitch<OpenACCClauseKind>(
8387
Tok.getIdentifierInfo()->getName())
8488
.Case("auto", OpenACCClauseKind::Auto)
89+
.Case("default", OpenACCClauseKind::Default)
8590
.Case("finalize", OpenACCClauseKind::Finalize)
8691
.Case("if_present", OpenACCClauseKind::IfPresent)
8792
.Case("independent", OpenACCClauseKind::Independent)
@@ -106,6 +111,17 @@ OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
106111
.Default(OpenACCAtomicKind::Invalid);
107112
}
108113

114+
OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) {
115+
if (!Tok.is(tok::identifier))
116+
return OpenACCDefaultClauseKind::Invalid;
117+
118+
return llvm::StringSwitch<OpenACCDefaultClauseKind>(
119+
Tok.getIdentifierInfo()->getName())
120+
.Case("none", OpenACCDefaultClauseKind::None)
121+
.Case("present", OpenACCDefaultClauseKind::Present)
122+
.Default(OpenACCDefaultClauseKind::Invalid);
123+
}
124+
109125
enum class OpenACCSpecialTokenKind {
110126
ReadOnly,
111127
DevNum,
@@ -176,6 +192,22 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
176192
llvm_unreachable("Unknown 'Kind' Passed");
177193
}
178194

195+
/// Used for cases where we expect an identifier-like token, but don't want to
196+
/// give awkward error messages in cases where it is accidentially a keyword.
197+
bool expectIdentifierOrKeyword(Parser &P) {
198+
Token Tok = P.getCurToken();
199+
200+
if (Tok.is(tok::identifier))
201+
return false;
202+
203+
if (!Tok.isAnnotation() && Tok.getIdentifierInfo() &&
204+
Tok.getIdentifierInfo()->isKeyword(P.getLangOpts()))
205+
return false;
206+
207+
P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
208+
return true;
209+
}
210+
179211
OpenACCDirectiveKind
180212
ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
181213
OpenACCDirectiveKindEx ExtDirKind) {
@@ -291,13 +323,56 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
291323
return DirKind;
292324
}
293325

326+
bool ClauseHasRequiredParens(OpenACCClauseKind Kind) {
327+
return Kind == OpenACCClauseKind::Default;
328+
}
329+
330+
bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
331+
BalancedDelimiterTracker Parens(P, tok::l_paren,
332+
tok::annot_pragma_openacc_end);
333+
334+
if (ClauseHasRequiredParens(Kind)) {
335+
if (Parens.expectAndConsume()) {
336+
// We are missing a paren, so assume that the person just forgot the
337+
// parameter. Return 'false' so we try to continue on and parse the next
338+
// clause.
339+
P.SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
340+
Parser::StopBeforeMatch);
341+
return false;
342+
}
343+
344+
switch (Kind) {
345+
case OpenACCClauseKind::Default: {
346+
Token DefKindTok = P.getCurToken();
347+
348+
if (expectIdentifierOrKeyword(P))
349+
break;
350+
351+
P.ConsumeToken();
352+
353+
if (getOpenACCDefaultClauseKind(DefKindTok) ==
354+
OpenACCDefaultClauseKind::Invalid)
355+
P.Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
356+
357+
break;
358+
}
359+
default:
360+
llvm_unreachable("Not a required parens type?");
361+
}
362+
363+
return Parens.consumeClose();
364+
}
365+
// FIXME: Handle optional parens
366+
return false;
367+
}
368+
294369
// The OpenACC Clause List is a comma or space-delimited list of clauses (see
295370
// the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't
296371
// really have its owner grammar and each individual one has its own definition.
297-
// However, they all are named with a single-identifier (or auto!) token,
298-
// followed in some cases by either braces or parens.
372+
// However, they all are named with a single-identifier (or auto/default!)
373+
// token, followed in some cases by either braces or parens.
299374
bool ParseOpenACCClause(Parser &P) {
300-
if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto))
375+
if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto, tok::kw_default))
301376
return P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
302377

303378
OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken());
@@ -309,8 +384,7 @@ bool ParseOpenACCClause(Parser &P) {
309384
// Consume the clause name.
310385
P.ConsumeToken();
311386

312-
// FIXME: For future clauses, we need to handle parens/etc below.
313-
return false;
387+
return ParseOpenACCClauseParams(P, Kind);
314388
}
315389

316390
// Skip until we see the end of pragma token, but don't consume it. This is us

clang/test/ParserOpenACC/parse-clauses.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,102 @@ void func() {
5454
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
5555
#pragma acc loop seq,
5656

57+
}
58+
59+
void DefaultClause() {
60+
// expected-error@+2{{expected '('}}
61+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
62+
#pragma acc serial loop default
63+
for(;;){}
64+
65+
// expected-error@+2{{expected '('}}
66+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
67+
#pragma acc serial default seq
68+
for(;;){}
69+
70+
// expected-error@+2{{expected '('}}
71+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
72+
#pragma acc serial default, seq
73+
for(;;){}
74+
75+
// expected-error@+4{{expected identifier}}
76+
// expected-error@+3{{expected ')'}}
77+
// expected-note@+2{{to match this '('}}
78+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
79+
#pragma acc serial default(
80+
for(;;){}
81+
82+
// expected-error@+4{{invalid value for 'default' clause; expected 'present' or 'none'}}
83+
// expected-error@+3{{expected ')'}}
84+
// expected-note@+2{{to match this '('}}
85+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
86+
#pragma acc serial default( seq
87+
for(;;){}
88+
89+
// expected-error@+4{{expected identifier}}
90+
// expected-error@+3{{expected ')'}}
91+
// expected-note@+2{{to match this '('}}
92+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
93+
#pragma acc serial default(, seq
94+
for(;;){}
95+
96+
// expected-error@+3{{expected '('}}
97+
// expected-error@+2{{expected identifier}}
98+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
99+
#pragma acc serial default)
100+
for(;;){}
101+
102+
// expected-error@+3{{expected '('}}
103+
// expected-error@+2{{expected identifier}}
104+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
105+
#pragma acc serial default) seq
106+
for(;;){}
107+
108+
// expected-error@+3{{expected '('}}
109+
// expected-error@+2{{expected identifier}}
110+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
111+
#pragma acc serial default), seq
112+
for(;;){}
113+
114+
// expected-error@+2{{expected identifier}}
115+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
116+
#pragma acc serial default()
117+
for(;;){}
118+
119+
// expected-error@+2{{expected identifier}}
120+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
121+
#pragma acc serial default() seq
122+
for(;;){}
123+
124+
// expected-error@+2{{expected identifier}}
125+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
126+
#pragma acc serial default(), seq
127+
for(;;){}
128+
129+
// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
130+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
131+
#pragma acc serial default(invalid)
132+
for(;;){}
133+
134+
// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
135+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
136+
#pragma acc serial default(auto) seq
137+
for(;;){}
138+
139+
// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
140+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
141+
#pragma acc serial default(invalid), seq
142+
for(;;){}
143+
144+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
145+
#pragma acc serial default(none)
146+
for(;;){}
147+
148+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
149+
#pragma acc serial default(present), seq
150+
for(;;){}
151+
152+
57153
}
58154

59155
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}

0 commit comments

Comments
 (0)