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

via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 7 17:29:21 PST 2023


Author: Erich Keane
Date: 2023-12-07T17:29:18-08:00
New Revision: df3db035d60ca2471d46166c08208c12307d20ef

URL: https://github.com/llvm/llvm-project/commit/df3db035d60ca2471d46166c08208c12307d20ef
DIFF: https://github.com/llvm/llvm-project/commit/df3db035d60ca2471d46166c08208c12307d20ef.diff

LOG: [OpenACC] Implement 'wait' construct parsing (#74752)

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

Added: 
    clang/test/ParserOpenACC/parse-wait-construct.c

Modified: 
    clang/include/clang/Basic/OpenACCKinds.h
    clang/include/clang/Parse/Parser.h
    clang/lib/Parse/ParseOpenACC.cpp

Removed: 
    


################################################################################
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..40b53dd180c79c 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)
@@ -82,6 +83,24 @@ OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
       .Default(OpenACCAtomicKind::Invalid);
 }
 
+enum class OpenACCSpecialTokenKind {
+  DevNum,
+  Queues,
+};
+
+bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {
+  if (!Tok.is(tok::identifier))
+    return false;
+
+  switch (Kind) {
+  case OpenACCSpecialTokenKind::DevNum:
+    return Tok.getIdentifierInfo()->isStr("devnum");
+  case OpenACCSpecialTokenKind::Queues:
+    return Tok.getIdentifierInfo()->isStr("queues");
+  }
+  llvm_unreachable("Unknown 'Kind' Passed");
+}
+
 bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
   if (!Tok.is(tok::identifier))
     return false;
@@ -123,6 +142,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 +272,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 (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
+      NextToken().is(tok::colon)) {
+    // Consume devnum.
+    ConsumeToken();
+    // Consume colon.
+    ConsumeToken();
+
+    ExprResult IntExpr =
+        getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+    if (IntExpr.isInvalid())
+      return true;
+
+    if (ExpectAndConsume(tok::colon))
+      return true;
+  }
+
+  // [ queues : ]
+  if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
+      NextToken().is(tok::colon)) {
+    // 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 +481,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
+}


        


More information about the cfe-commits mailing list