Skip to content

Commit

Permalink
[OpenACC] Implement 'if' clause
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
erichkeane committed Jan 8, 2024
1 parent 16cd344 commit e6b7c8c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 3 deletions.
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/OpenACCKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ enum class OpenACCClauseKind {
/// 'default' clause, allowed on parallel, serial, kernel (and compound)
/// constructs.
Default,
/// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
/// Executable Constructs, and Combined Constructs.
If,
/// Represents an invalid clause, for the purposes of parsing.
Invalid,
};
Expand Down
26 changes: 23 additions & 3 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
if (Tok.is(tok::kw_default))
return OpenACCClauseKind::Default;

// if is also a keyword, make sure we parse it correctly.
if (Tok.is(tok::kw_if))
return OpenACCClauseKind::If;

if (!Tok.is(tok::identifier))
return OpenACCClauseKind::Invalid;

Expand All @@ -88,6 +92,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
.Case("auto", OpenACCClauseKind::Auto)
.Case("default", OpenACCClauseKind::Default)
.Case("finalize", OpenACCClauseKind::Finalize)
.Case("if", OpenACCClauseKind::If)
.Case("if_present", OpenACCClauseKind::IfPresent)
.Case("independent", OpenACCClauseKind::Independent)
.Case("nohost", OpenACCClauseKind::NoHost)
Expand Down Expand Up @@ -324,7 +329,7 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
}

bool ClauseHasRequiredParens(OpenACCClauseKind Kind) {
return Kind == OpenACCClauseKind::Default;
return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If;
}

bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
Expand Down Expand Up @@ -356,6 +361,19 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {

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

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

Expand Down
84 changes: 84 additions & 0 deletions clang/test/ParserOpenACC/parse-clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,92 @@ void DefaultClause() {
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial default(present), seq
for(;;){}
}

void IfClause() {
// expected-error@+2{{expected '('}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial loop if
for(;;){}

// expected-error@+2{{expected '('}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if seq
for(;;){}

// expected-error@+2{{expected '('}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if, seq
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if(
for(;;){}

// expected-error@+2{{use of undeclared identifier 'seq'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if( seq
for(;;){}

// expected-error@+3{{expected expression}}
// expected-error@+2{{use of undeclared identifier 'seq'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if(, seq
for(;;){}

// expected-error@+3{{expected '('}}
// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if)
for(;;){}

// expected-error@+3{{expected '('}}
// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if) seq
for(;;){}

// expected-error@+3{{expected '('}}
// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if), seq
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if()
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if() seq
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if(), seq
for(;;){}

// expected-error@+2{{use of undeclared identifier 'invalid_expr'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if(invalid_expr)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if() seq
for(;;){}

int i, j;

// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if(i > j)
for(;;){}

// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial if(1+5>3), seq
for(;;){}
}

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

0 comments on commit e6b7c8c

Please sign in to comment.