Skip to content

Commit e6b7c8c

Browse files
committed
[OpenACC] Implement 'if' clause
The 'if' clause takes a required 'condition' expression. This patch implements that as an expression we will later ensure is convertible to a binary expression.
1 parent 16cd344 commit e6b7c8c

File tree

3 files changed

+110
-3
lines changed

3 files changed

+110
-3
lines changed

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ enum class OpenACCClauseKind {
9393
/// 'default' clause, allowed on parallel, serial, kernel (and compound)
9494
/// constructs.
9595
Default,
96+
/// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
97+
/// Executable Constructs, and Combined Constructs.
98+
If,
9699
/// Represents an invalid clause, for the purposes of parsing.
97100
Invalid,
98101
};

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
8080
if (Tok.is(tok::kw_default))
8181
return OpenACCClauseKind::Default;
8282

83+
// if is also a keyword, make sure we parse it correctly.
84+
if (Tok.is(tok::kw_if))
85+
return OpenACCClauseKind::If;
86+
8387
if (!Tok.is(tok::identifier))
8488
return OpenACCClauseKind::Invalid;
8589

@@ -88,6 +92,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
8892
.Case("auto", OpenACCClauseKind::Auto)
8993
.Case("default", OpenACCClauseKind::Default)
9094
.Case("finalize", OpenACCClauseKind::Finalize)
95+
.Case("if", OpenACCClauseKind::If)
9196
.Case("if_present", OpenACCClauseKind::IfPresent)
9297
.Case("independent", OpenACCClauseKind::Independent)
9398
.Case("nohost", OpenACCClauseKind::NoHost)
@@ -324,7 +329,7 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
324329
}
325330

326331
bool ClauseHasRequiredParens(OpenACCClauseKind Kind) {
327-
return Kind == OpenACCClauseKind::Default;
332+
return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If;
328333
}
329334

330335
bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
@@ -356,6 +361,19 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
356361

357362
break;
358363
}
364+
case OpenACCClauseKind::If: {
365+
// FIXME: It isn't clear if the spec saying 'condition' means the same as
366+
// it does in an if/while/etc (See ParseCXXCondition), however as it was
367+
// written with Fortran/C in mind, we're going to assume it just means an
368+
// 'expression evaluating to boolean'.
369+
ExprResult CondExpr =
370+
P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression());
371+
// An invalid expression can be just about anything, so just give up on
372+
// this clause list.
373+
if (CondExpr.isInvalid())
374+
return true;
375+
break;
376+
}
359377
default:
360378
llvm_unreachable("Not a required parens type?");
361379
}
@@ -372,8 +390,10 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
372390
// However, they all are named with a single-identifier (or auto/default!)
373391
// token, followed in some cases by either braces or parens.
374392
bool ParseOpenACCClause(Parser &P) {
375-
if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto, tok::kw_default))
376-
return P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
393+
// A number of clause names are actually keywords, so accept a keyword that
394+
// can be converted to a name.
395+
if (expectIdentifierOrKeyword(P))
396+
return true;
377397

378398
OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken());
379399

clang/test/ParserOpenACC/parse-clauses.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,92 @@ void DefaultClause() {
148148
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
149149
#pragma acc serial default(present), seq
150150
for(;;){}
151+
}
152+
153+
void IfClause() {
154+
// expected-error@+2{{expected '('}}
155+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
156+
#pragma acc serial loop if
157+
for(;;){}
151158

159+
// expected-error@+2{{expected '('}}
160+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
161+
#pragma acc serial if seq
162+
for(;;){}
163+
164+
// expected-error@+2{{expected '('}}
165+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
166+
#pragma acc serial if, seq
167+
for(;;){}
168+
169+
// expected-error@+2{{expected expression}}
170+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
171+
#pragma acc serial if(
172+
for(;;){}
152173

174+
// expected-error@+2{{use of undeclared identifier 'seq'}}
175+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
176+
#pragma acc serial if( seq
177+
for(;;){}
178+
179+
// expected-error@+3{{expected expression}}
180+
// expected-error@+2{{use of undeclared identifier 'seq'}}
181+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
182+
#pragma acc serial if(, seq
183+
for(;;){}
184+
185+
// expected-error@+3{{expected '('}}
186+
// expected-error@+2{{expected identifier}}
187+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
188+
#pragma acc serial if)
189+
for(;;){}
190+
191+
// expected-error@+3{{expected '('}}
192+
// expected-error@+2{{expected identifier}}
193+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
194+
#pragma acc serial if) seq
195+
for(;;){}
196+
197+
// expected-error@+3{{expected '('}}
198+
// expected-error@+2{{expected identifier}}
199+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
200+
#pragma acc serial if), seq
201+
for(;;){}
202+
203+
// expected-error@+2{{expected expression}}
204+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
205+
#pragma acc serial if()
206+
for(;;){}
207+
208+
// expected-error@+2{{expected expression}}
209+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
210+
#pragma acc serial if() seq
211+
for(;;){}
212+
213+
// expected-error@+2{{expected expression}}
214+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
215+
#pragma acc serial if(), seq
216+
for(;;){}
217+
218+
// expected-error@+2{{use of undeclared identifier 'invalid_expr'}}
219+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
220+
#pragma acc serial if(invalid_expr)
221+
for(;;){}
222+
223+
// expected-error@+2{{expected expression}}
224+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
225+
#pragma acc serial if() seq
226+
for(;;){}
227+
228+
int i, j;
229+
230+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
231+
#pragma acc serial if(i > j)
232+
for(;;){}
233+
234+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
235+
#pragma acc serial if(1+5>3), seq
236+
for(;;){}
153237
}
154238

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

0 commit comments

Comments
 (0)