-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[OpenACC] Implement 'wait' construct parsing #74752
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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'.
@llvm/pr-subscribers-clang Author: Erich Keane (erichkeane) ChangesThe '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'. Full diff: https://github.com/llvm/llvm-project/pull/74752.diff 4 Files Affected:
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 449a75638b43f5..62c0a4c1a9dea4 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -53,7 +53,7 @@ enum class OpenACCDirectiveKind {
Shutdown,
Set,
Update,
- // FIXME: wait construct.
+ Wait,
// Procedure Calls in Compute Regions.
Routine,
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 32d0b76c35b0d7..06634982351647 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3544,6 +3544,7 @@ class Parser : public CodeCompletionHandler {
void ParseOpenACCCacheVarList();
/// Parses a single variable in a variable list for the 'cache' construct.
bool ParseOpenACCCacheVar();
+ bool ParseOpenACCWaitArgument();
private:
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 71cb665a563271..0bdf8da26bb01e 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -56,6 +56,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {
.Case("shutdown", OpenACCDirectiveKind::Shutdown)
.Case("set", OpenACCDirectiveKind::Shutdown)
.Case("update", OpenACCDirectiveKind::Update)
+ .Case("wait", OpenACCDirectiveKind::Wait)
.Default(OpenACCDirectiveKind::Invalid);
if (DirKind != OpenACCDirectiveKind::Invalid)
@@ -123,6 +124,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
return Tok.getIdentifierInfo()->isStr("set");
case OpenACCDirectiveKind::Update:
return Tok.getIdentifierInfo()->isStr("update");
+ case OpenACCDirectiveKind::Wait:
+ return Tok.getIdentifierInfo()->isStr("wait");
case OpenACCDirectiveKind::Invalid:
return false;
}
@@ -251,6 +254,67 @@ void ParseOpenACCClauseList(Parser &P) {
} // namespace
+/// OpenACC 3.3, section 2.16:
+/// In this section and throughout the specification, the term wait-argument
+/// means:
+/// [ devnum : int-expr : ] [ queues : ] async-argument-list
+bool Parser::ParseOpenACCWaitArgument() {
+ // [devnum : int-expr : ]
+ if (Tok.is(tok::identifier) && NextToken().is(tok::colon) &&
+ Tok.getIdentifierInfo()->isStr("devnum")) {
+ // Consume devnum.
+ ConsumeToken();
+ // Consume colon.
+ ConsumeToken();
+
+ ExprResult IntExpr =
+ getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ if (IntExpr.isInvalid())
+ return true;
+
+ if (ExpectAndConsume(tok::colon))
+ return true;
+ }
+
+ // [ queues : ]
+ if (Tok.is(tok::identifier) && NextToken().is(tok::colon) &&
+ Tok.getIdentifierInfo()->isStr("queues")) {
+ // Consume queues.
+ ConsumeToken();
+ // Consume colon.
+ ConsumeToken();
+ }
+
+ // OpenACC 3.3, section 2.16:
+ // the term 'async-argument' means a nonnegative scalar integer expression, or
+ // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined
+ // in the C header file and the Fortran opacc module.
+ //
+ // We are parsing this simply as list of assignment expressions (to avoid
+ // comma being troublesome), and will ensure it is an integral type. The
+ // 'special' types are defined as macros, so we can't really check those
+ // (other than perhaps as values at one point?), but the standard does say it
+ // is implementation-defined to use any other negative value.
+ //
+ //
+ bool FirstArg = true;
+ while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
+ if (!FirstArg) {
+ if (ExpectAndConsume(tok::comma))
+ return true;
+ }
+ FirstArg = false;
+
+ ExprResult CurArg =
+ getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+
+ if (CurArg.isInvalid())
+ return true;
+ }
+
+ return false;
+}
+
ExprResult Parser::ParseOpenACCIDExpression() {
ExprResult Res;
if (getLangOpts().CPlusPlus) {
@@ -399,6 +463,13 @@ void Parser::ParseOpenACCDirective() {
// so we can always consume the close.
T.consumeClose();
break;
+ case OpenACCDirectiveKind::Wait:
+ // OpenACC has an optional paren-wrapped 'wait-argument'.
+ if (ParseOpenACCWaitArgument())
+ T.skipToEnd();
+ else
+ T.consumeClose();
+ break;
}
} else if (DirKind == OpenACCDirectiveKind::Cache) {
// Cache's paren var-list is required, so error here if it isn't provided.
diff --git a/clang/test/ParserOpenACC/parse-wait-construct.c b/clang/test/ParserOpenACC/parse-wait-construct.c
new file mode 100644
index 00000000000000..9b210bc7094210
--- /dev/null
+++ b/clang/test/ParserOpenACC/parse-wait-construct.c
@@ -0,0 +1,157 @@
+// RUN: %clang_cc1 %s -verify -fopenacc
+
+void func() {
+ int i, j;
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait
+
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait clause-list
+
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait ()
+
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait () clause-list
+
+ // expected-error@+4{{expected expression}}
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum:
+
+ // expected-error@+2{{expected expression}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum:)
+
+ // expected-error@+3{{expected expression}}
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum:) clause-list
+
+ // expected-error@+4{{expected ':'}}
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j
+
+ // expected-error@+2{{expected ':'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j)
+
+ // expected-error@+3{{expected ':'}}
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j) clause-list
+
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:)
+
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:) clause-list
+
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j:queues:
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j:queues:)
+
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (devnum: i + j:queues:) clause-list
+
+ // expected-error@+4{{use of undeclared identifier 'devnum'}}
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:devnum: i + j
+
+ // expected-error@+2{{use of undeclared identifier 'devnum'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:devnum: i + j)
+
+ // expected-error@+3{{use of undeclared identifier 'devnum'}}
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait (queues:devnum: i + j) clause-list
+
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(i, j, 1+1, 3.3
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(i, j, 1+1, 3.3)
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(i, j, 1+1, 3.3) clause-list
+
+ // expected-error@+4{{expected expression}}
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(,
+
+ // expected-error@+2{{expected expression}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(,)
+
+ // expected-error@+3{{expected expression}}
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(,) clause-list
+
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3
+
+ // expected-error@+4{{expected expression}}
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3,
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3)
+
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(queues:i, j, 1+1, 3.3) clause-list
+
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:i, j, 1+1, 3.3
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:i, j, 1+1, 3.3)
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:i, j, 1+1, 3.3) clause-list
+
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3)
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+ #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) clause-list
+}
|
clang/lib/Parse/ParseOpenACC.cpp
Outdated
bool Parser::ParseOpenACCWaitArgument() { | ||
// [devnum : int-expr : ] | ||
if (Tok.is(tok::identifier) && NextToken().is(tok::colon) && | ||
Tok.getIdentifierInfo()->isStr("devnum")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think better to introduce function, similar to isOpenACCDirectiveKind, something like isOpenACCStandardKind or something similar to check for some clauses-like tokens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I intended to do that for clauses themselves.
These are construct-specific 'key-token' things, which i see value in something like that, at least as far as simplification. I've chosen the name 'special token kind', as I don't think "StandardKind' really means what is being reflected here.
At the moment, we have 3 options for it (though only 2 for 'wait'), so once this patch goes in, I'll update the 'readonly' one from the last patch to use this infrastructure as well.
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'.