Skip to content

Commit

Permalink
[OpenACC] Implement 'self' clause parsing
Browse files Browse the repository at this point in the history
The 'self' clause takes an optional 'condition' expression, same as the
non-optional expression taken by the 'if' clause.  This patch extracts
the 'condition' expression to a separate function, and implements the
'optional parens' infrastructure for clauses, then implements 'self'
parsing.
  • Loading branch information
erichkeane committed Jan 8, 2024
1 parent e72c716 commit 87f67c2
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 7 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/OpenACCKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ enum class OpenACCClauseKind {
/// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
/// Executable Constructs, and Combined Constructs.
If,
/// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
Self,
/// Represents an invalid clause, for the purposes of parsing.
Invalid,
};
Expand Down
37 changes: 30 additions & 7 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
.Case("if_present", OpenACCClauseKind::IfPresent)
.Case("independent", OpenACCClauseKind::Independent)
.Case("nohost", OpenACCClauseKind::NoHost)
.Case("self", OpenACCClauseKind::Self)
.Case("seq", OpenACCClauseKind::Seq)
.Case("vector", OpenACCClauseKind::Vector)
.Case("worker", OpenACCClauseKind::Worker)
Expand Down Expand Up @@ -328,10 +329,22 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
return DirKind;
}

bool ClauseHasOptionalParens(OpenACCClauseKind Kind) {
return Kind == OpenACCClauseKind::Self;
}

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

ExprResult ParseOpenACCConditionalExpr(Parser &P) {
// 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'.
return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression());
}

bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
BalancedDelimiterTracker Parens(P, tok::l_paren,
tok::annot_pragma_openacc_end);
Expand Down Expand Up @@ -362,12 +375,7 @@ 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());
ExprResult CondExpr = ParseOpenACCConditionalExpr(P);
// An invalid expression can be just about anything, so just give up on
// this clause list.
if (CondExpr.isInvalid())
Expand All @@ -379,8 +387,23 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
}

return Parens.consumeClose();
} else if (ClauseHasOptionalParens(Kind)) {
if (!Parens.consumeOpen()) {
switch (Kind) {
case OpenACCClauseKind::Self: {
ExprResult CondExpr = ParseOpenACCConditionalExpr(P);
// 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 an optional parens type?");
}
Parens.consumeClose();
}
}
// FIXME: Handle optional parens
return false;
}

Expand Down
79 changes: 79 additions & 0 deletions clang/test/ParserOpenACC/parse-clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,85 @@ void IfClause() {
for(;;){}
}

void SyncClause() {
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial loop self
for(;;){}

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

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

// expected-error@+2{{use of undeclared identifier 'seq'}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial loop self( 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 loop self(, seq
for(;;){}

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

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

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


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

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

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

int i, j;

// expected-error@+3{{expected ')'}}
// expected-note@+2{{to match this '('}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial self(i > j
for(;;){}

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

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

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

// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc routine worker, vector, seq, nohost
void bar();
Expand Down

0 comments on commit 87f67c2

Please sign in to comment.