[clang] [OpenACC] Implement 'wait' construct parsing (PR #74752)

via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 7 11:37:34 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Erich Keane (erichkeane)

<details>
<summary>Changes</summary>

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'.

---
Full diff: https://github.com/llvm/llvm-project/pull/74752.diff


4 Files Affected:

- (modified) clang/include/clang/Basic/OpenACCKinds.h (+1-1) 
- (modified) clang/include/clang/Parse/Parser.h (+1) 
- (modified) clang/lib/Parse/ParseOpenACC.cpp (+71) 
- (added) clang/test/ParserOpenACC/parse-wait-construct.c (+157) 


``````````diff
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 at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait
+
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait clause-list
+
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait ()
+
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait () clause-list
+
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum:
+
+  // expected-error at +2{{expected expression}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum:)
+
+  // expected-error at +3{{expected expression}}
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum:) clause-list
+
+  // expected-error at +4{{expected ':'}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum: i + j
+
+  // expected-error at +2{{expected ':'}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum: i + j)
+
+  // expected-error at +3{{expected ':'}}
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum: i + j) clause-list
+
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (queues:
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (queues:)
+
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (queues:) clause-list
+
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum: i + j:queues:
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum: i + j:queues:)
+
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (devnum: i + j:queues:) clause-list
+
+  // expected-error at +4{{use of undeclared identifier 'devnum'}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (queues:devnum: i + j
+
+  // expected-error at +2{{use of undeclared identifier 'devnum'}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (queues:devnum: i + j)
+
+  // expected-error at +3{{use of undeclared identifier 'devnum'}}
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait (queues:devnum: i + j) clause-list
+
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(i, j, 1+1, 3.3
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(i, j, 1+1, 3.3)
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(i, j, 1+1, 3.3) clause-list
+
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(,
+
+  // expected-error at +2{{expected expression}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(,)
+
+  // expected-error at +3{{expected expression}}
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(,) clause-list
+
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(queues:i, j, 1+1, 3.3
+
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(queues:i, j, 1+1, 3.3,
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(queues:i, j, 1+1, 3.3)
+
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(queues:i, j, 1+1, 3.3) clause-list
+
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(devnum:3:i, j, 1+1, 3.3
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(devnum:3:i, j, 1+1, 3.3)
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(devnum:3:i, j, 1+1, 3.3) clause-list
+
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3)
+  // expected-warning at +2{{OpenACC clause parsing not yet implemented}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+  #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) clause-list
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/74752


More information about the cfe-commits mailing list