https://github.com/erichkeane updated 
https://github.com/llvm/llvm-project/pull/74324

>From 31fe05335fce5f7c593e4c3f3595c548cf54bba0 Mon Sep 17 00:00:00 2001
From: erichkeane <eke...@nvidia.com>
Date: Wed, 29 Nov 2023 11:12:02 -0800
Subject: [PATCH 1/4] [OpenACC] Implement 'cache' construct parsing

The 'cache' construct takes a list of 'vars', which are array-section
style definitions. This patch implements the parsing, leaving the lower
bound and length of the bound as expressions, so that we can validate
they are the correct 'thing' in sema.
---
 clang/include/clang/Basic/OpenACCKinds.h      |   2 +-
 clang/include/clang/Parse/Parser.h            |   7 +-
 clang/lib/Parse/ParseOpenACC.cpp              |  92 ++++++++-
 .../ParserOpenACC/parse-cache-construct.c     | 178 ++++++++++++++++++
 .../ParserOpenACC/parse-cache-construct.cpp   |  51 +++++
 5 files changed, 322 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/ParserOpenACC/parse-cache-construct.c
 create mode 100644 clang/test/ParserOpenACC/parse-cache-construct.cpp

diff --git a/clang/include/clang/Basic/OpenACCKinds.h 
b/clang/include/clang/Basic/OpenACCKinds.h
index 1a5bf7e0e831c..449a75638b43f 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -34,7 +34,7 @@ enum class OpenACCDirectiveKind {
 
   // Misc.
   Loop,
-  // FIXME: 'cache'
+  Cache,
 
   // Combined Constructs.
   ParallelLoop,
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index ca29ce46873e8..b0c7f3eca666b 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3538,7 +3538,12 @@ class Parser : public CodeCompletionHandler {
 
 private:
   void ParseOpenACCDirective();
-  ExprResult ParseOpenACCRoutineName();
+  /// Helper that parses an ID Expression based on the language options.
+  ExprResult ParseOpenACCIDExpression();
+  /// Parses the variable list for the `cache` construct.
+  void ParseOpenACCCacheVarList();
+  /// Parses a single variable in a variable list for the 'cache' construct.
+  void ParseOpenACCCacheVar();
 
 private:
   
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 4021d50318561..2787f96a9ef42 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -45,6 +45,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(StringRef 
Name) {
           .Case("data", OpenACCDirectiveKind::Data)
           .Case("host_data", OpenACCDirectiveKind::HostData)
           .Case("loop", OpenACCDirectiveKind::Loop)
+          .Case("cache", OpenACCDirectiveKind::Cache)
           .Case("atomic", OpenACCDirectiveKind::Atomic)
           .Case("routine", OpenACCDirectiveKind::Routine)
           .Case("declare", OpenACCDirectiveKind::Declare)
@@ -88,6 +89,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, 
StringRef Tok) {
     return Tok == "host_data";
   case OpenACCDirectiveKind::Loop:
     return Tok == "loop";
+  case OpenACCDirectiveKind::Cache:
+    return Tok == "cache";
 
   case OpenACCDirectiveKind::ParallelLoop:
   case OpenACCDirectiveKind::SerialLoop:
@@ -237,10 +240,7 @@ void ParseOpenACCClauseList(Parser &P) {
 
 } // namespace
 
-// Routine has an optional paren-wrapped name of a function in the local scope.
-// We parse the name, emitting any diagnostics
-ExprResult Parser::ParseOpenACCRoutineName() {
-
+ExprResult Parser::ParseOpenACCIDExpression() {
   ExprResult Res;
   if (getLangOpts().CPlusPlus) {
     Res = ParseCXXIdExpression(/*isAddressOfOperand=*/false);
@@ -248,8 +248,10 @@ ExprResult Parser::ParseOpenACCRoutineName() {
     // There isn't anything quite the same as ParseCXXIdExpression for C, so we
     // need to get the identifier, then call into Sema ourselves.
 
-    if (expectIdentifier())
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_expected) << tok::identifier;
       return ExprError();
+    }
 
     Token FuncName = getCurToken();
     UnqualifiedId Name;
@@ -268,6 +270,71 @@ ExprResult Parser::ParseOpenACCRoutineName() {
   return getActions().CorrectDelayedTyposInExpr(Res);
 }
 
+void Parser::ParseOpenACCCacheVar() {
+  ExprResult ArrayName = ParseOpenACCIDExpression();
+  // FIXME: Pass this to Sema.
+  (void)ArrayName;
+
+  // If the expression is invalid, just continue parsing the brackets, there
+  // is likely other useful diagnostics we can emit inside of those.
+
+  BalancedDelimiterTracker SquareBrackets(*this, tok::l_square,
+                                          tok::annot_pragma_openacc_end);
+
+  // Square brackets are required, so error here, and try to recover by moving
+  // until the next comma, or the close paren/end of pragma.
+  if (SquareBrackets.expectAndConsume()) {
+    SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
+              Parser::StopBeforeMatch);
+    return;
+  }
+
+  ExprResult Lower = getActions().CorrectDelayedTyposInExpr(ParseExpression());
+  // FIXME: Pass this to Sema.
+  (void)Lower;
+
+  // The 'length' expression is optional, as this could be a single array
+  // element. If there is no colon, we can treat it as that.
+  if (getCurToken().is(tok::colon)) {
+    ConsumeToken();
+    ExprResult Length =
+        getActions().CorrectDelayedTyposInExpr(ParseExpression());
+    // FIXME: Pass this to Sema.
+    (void)Length;
+  }
+
+  // Diagnose the square bracket being in the wrong place and continue.
+  SquareBrackets.consumeClose();
+}
+
+void Parser::ParseOpenACCCacheVarList() {
+  // If this is the end of the line, just return 'false' and count on the close
+  // paren diagnostic to catch the issue.
+  if (getCurToken().isAnnotation())
+    return;
+
+  // The VarList is an optional `readonly:` followed by a list of a variable
+  // specifications.  First, see if we have `readonly:`, else we back-out and
+  // treat it like the beginning of a reference to a potentially-existing
+  // `readonly` variable.
+  if (getPreprocessor().getSpelling(getCurToken()) == "readonly" &&
+      NextToken().is(tok::colon)) {
+    // Consume both tokens.
+    ConsumeToken();
+    ConsumeToken();
+    // FIXME: Record that this is a 'readonly' so that we can use that during
+    // Sema/AST generation.
+  }
+
+  bool FirstArray = true;
+  while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
+    if (!FirstArray)
+      ExpectAndConsume(tok::comma);
+    FirstArray = false;
+    ParseOpenACCCacheVar();
+  }
+}
+
 void Parser::ParseOpenACCDirective() {
   OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);
 
@@ -289,7 +356,9 @@ void Parser::ParseOpenACCDirective() {
       T.skipToEnd();
       break;
     case OpenACCDirectiveKind::Routine: {
-      ExprResult RoutineName = ParseOpenACCRoutineName();
+      // Routine has an optional paren-wrapped name of a function in the local
+      // scope. We parse the name, emitting any diagnostics
+      ExprResult RoutineName = ParseOpenACCIDExpression();
       // If the routine name is invalid, just skip until the closing paren to
       // recover more gracefully.
       if (RoutineName.isInvalid())
@@ -298,7 +367,18 @@ void Parser::ParseOpenACCDirective() {
         T.consumeClose();
       break;
     }
+    case OpenACCDirectiveKind::Cache:
+      ParseOpenACCCacheVarList();
+      // The ParseOpenACCCacheVarList function manages to recover from 
failures,
+      // so we can always consume the close.
+      T.consumeClose();
+      break;
     }
+  } else if (DirKind == OpenACCDirectiveKind::Cache) {
+    // Cache's paren var-list is required, so error here if it isn't provided.
+    // We know that the consumeOpen above left the first non-paren here, so use
+    // expectAndConsume to emit the proper dialog, then continue.
+    (void)T.expectAndConsume();
   }
 
   // Parses the list of clauses, if present.
diff --git a/clang/test/ParserOpenACC/parse-cache-construct.c 
b/clang/test/ParserOpenACC/parse-cache-construct.c
new file mode 100644
index 0000000000000..5c0d363449e99
--- /dev/null
+++ b/clang/test/ParserOpenACC/parse-cache-construct.c
@@ -0,0 +1,178 @@
+// RUN: %clang_cc1 %s -verify -fopenacc
+
+char *getArrayPtr();
+void func() {
+  char Array[10];
+  char *ArrayPtr = getArrayPtr();
+  int *readonly;
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{expected '('}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // 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 cache clause list
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache()
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache() clause-list
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+3{{expected ')'}}
+    // expected-note@+2{{to match this '('}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+5{{use of undeclared identifier 'invalid'}}
+    // 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 cache(invalid
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // 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 cache(ArrayPtr
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+3{{use of undeclared identifier 'invalid'}}
+    // expected-error@+2{{expected '['}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(invalid)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{expected '['}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(ArrayPtr)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+6{{expected expression}}
+    // expected-error@+5{{expected ']'}}
+    // expected-note@+4{{to match this '['}}
+    // expected-error@+3{{expected ')'}}
+    // expected-note@+2{{to match this '('}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(ArrayPtr[
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // 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 cache(ArrayPtr[, 5)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // 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 cache(Array[)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(Array[*readonly])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+6{{expected expression}}
+    // expected-error@+5{{expected ']'}}
+    // expected-note@+4{{to match this '['}}
+    // expected-error@+3{{expected ')'}}
+    // expected-note@+2{{to match this '('}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(Array[*readonly:
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{expected '['}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{expected '['}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{expected expression}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5:])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5:*readonly])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{expected '['}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5:*readonly], Array)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5:*readonly], Array[*readonly:3])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5 + i:*readonly], Array[*readonly + 
i:3])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+5{{expected identifier}}
+    // 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 cache(readonly:ArrayPtr[5:*readonly],
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+3{{expected identifier}}
+    // expected-error@+2{{expected '['}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5:*readonly],)
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+2{{left operand of comma operator has no effect}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5,6:*readonly])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+2{{left operand of comma operator has no effect}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(readonly:ArrayPtr[5:3, *readonly], ArrayPtr[0])
+  }
+
+}
diff --git a/clang/test/ParserOpenACC/parse-cache-construct.cpp 
b/clang/test/ParserOpenACC/parse-cache-construct.cpp
new file mode 100644
index 0000000000000..68e25e1c8321f
--- /dev/null
+++ b/clang/test/ParserOpenACC/parse-cache-construct.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 %s -verify -fopenacc
+
+namespace NS {
+  static char* NSArray;// expected-note{{declared here}}
+  static int NSInt;// expected-note 2{{declared here}}
+}
+char *getArrayPtr();
+template<typename T, int I>
+void func() {
+  char *ArrayPtr = getArrayPtr();
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(ArrayPtr[T::value + I:I + 5], T::array[(i + T::value, 
5): 6])
+  }
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(NS::NSArray[NS::NSInt])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(NS::NSArray[NS::NSInt : NS::NSInt])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{use of undeclared identifier 'NSArray'; did you mean 
'NS::NSArray'}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(NSArray[NS::NSInt : NS::NSInt])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 
'NS::NSInt'}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(NS::NSArray[NSInt : NS::NSInt])
+  }
+
+  for (int i = 0; i  < 10; ++i) {
+    // expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 
'NS::NSInt'}}
+    // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
+    #pragma acc cache(NS::NSArray[NS::NSInt : NSInt])
+  }
+}
+
+struct S {
+  static constexpr int value = 5;
+  static constexpr char array[] ={1,2,3,4,5};
+};
+
+void use() {
+  func<S, 5>();
+}

>From 83aaae60628ccc8ea0f4c409e9ea48b695553151 Mon Sep 17 00:00:00 2001
From: erichkeane <eke...@nvidia.com>
Date: Tue, 5 Dec 2023 07:29:28 -0800
Subject: [PATCH 2/4] Explicitly diagnose missing '('

---
 clang/lib/Parse/ParseOpenACC.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 2787f96a9ef42..27ce207a6a603 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -376,9 +376,9 @@ void Parser::ParseOpenACCDirective() {
     }
   } else if (DirKind == OpenACCDirectiveKind::Cache) {
     // Cache's paren var-list is required, so error here if it isn't provided.
-    // We know that the consumeOpen above left the first non-paren here, so use
-    // expectAndConsume to emit the proper dialog, then continue.
-    (void)T.expectAndConsume();
+    // We know that the consumeOpen above left the first non-paren here, so
+    // diagnose, then continue as if it was completely omitted.
+    Diag(Tok, diag::err_expected) << tok::l_paren;
   }
 
   // Parses the list of clauses, if present.

>From fa9ff495024ad477796f1a3dd8800c2b9b0c8ce7 Mon Sep 17 00:00:00 2001
From: erichkeane <eke...@nvidia.com>
Date: Tue, 5 Dec 2023 08:09:09 -0800
Subject: [PATCH 3/4] add standards comment to the cache functions

---
 clang/lib/Parse/ParseOpenACC.cpp | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 27ce207a6a603..14b7fe1289ec5 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -270,6 +270,14 @@ ExprResult Parser::ParseOpenACCIDExpression() {
   return getActions().CorrectDelayedTyposInExpr(Res);
 }
 
+/// OpenACC 3.3, section 2.10:
+/// A 'var' in a cache directive must be a single array element or a simple
+/// subarray.  In C and C++, a simple subarray is an array name followed by an
+/// extended array range specification in brackets, with a start and length 
such
+/// as:
+///
+/// arr[lower:length]
+///
 void Parser::ParseOpenACCCacheVar() {
   ExprResult ArrayName = ParseOpenACCIDExpression();
   // FIXME: Pass this to Sema.
@@ -307,6 +315,10 @@ void Parser::ParseOpenACCCacheVar() {
   SquareBrackets.consumeClose();
 }
 
+/// OpenACC 3.3, section 2.10:
+/// In C and C++, the syntax of the cache directive is:
+///
+/// #pragma acc cache ([readonly:]var-list) new-line
 void Parser::ParseOpenACCCacheVarList() {
   // If this is the end of the line, just return 'false' and count on the close
   // paren diagnostic to catch the issue.

>From 0d11f6c24814cbfdb1e175b23ea39a284f559e43 Mon Sep 17 00:00:00 2001
From: erichkeane <eke...@nvidia.com>
Date: Tue, 5 Dec 2023 09:08:22 -0800
Subject: [PATCH 4/4] Make parse-cache-var fail early and exist, handle it
 correctly

---
 clang/include/clang/Parse/Parser.h            |  2 +-
 clang/lib/Parse/ParseOpenACC.cpp              | 22 +++---
 .../ParserOpenACC/parse-cache-construct.c     | 78 ++++++++-----------
 .../ParserOpenACC/parse-cache-construct.cpp   | 12 +--
 4 files changed, 52 insertions(+), 62 deletions(-)

diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index b0c7f3eca666b..32d0b76c35b0d 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3543,7 +3543,7 @@ class Parser : public CodeCompletionHandler {
   /// Parses the variable list for the `cache` construct.
   void ParseOpenACCCacheVarList();
   /// Parses a single variable in a variable list for the 'cache' construct.
-  void ParseOpenACCCacheVar();
+  bool ParseOpenACCCacheVar();
 
 private:
   
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 14b7fe1289ec5..3132e043132bc 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -278,10 +278,10 @@ ExprResult Parser::ParseOpenACCIDExpression() {
 ///
 /// arr[lower:length]
 ///
-void Parser::ParseOpenACCCacheVar() {
+bool Parser::ParseOpenACCCacheVar() {
   ExprResult ArrayName = ParseOpenACCIDExpression();
-  // FIXME: Pass this to Sema.
-  (void)ArrayName;
+  if (ArrayName.isInvalid())
+    return true;
 
   // If the expression is invalid, just continue parsing the brackets, there
   // is likely other useful diagnostics we can emit inside of those.
@@ -294,12 +294,12 @@ void Parser::ParseOpenACCCacheVar() {
   if (SquareBrackets.expectAndConsume()) {
     SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
               Parser::StopBeforeMatch);
-    return;
+    return true;
   }
 
   ExprResult Lower = getActions().CorrectDelayedTyposInExpr(ParseExpression());
-  // FIXME: Pass this to Sema.
-  (void)Lower;
+  if (Lower.isInvalid())
+    return true;
 
   // The 'length' expression is optional, as this could be a single array
   // element. If there is no colon, we can treat it as that.
@@ -307,12 +307,12 @@ void Parser::ParseOpenACCCacheVar() {
     ConsumeToken();
     ExprResult Length =
         getActions().CorrectDelayedTyposInExpr(ParseExpression());
-    // FIXME: Pass this to Sema.
-    (void)Length;
+    if (Length.isInvalid())
+      return true;
   }
 
   // Diagnose the square bracket being in the wrong place and continue.
-  SquareBrackets.consumeClose();
+  return SquareBrackets.consumeClose();
 }
 
 /// OpenACC 3.3, section 2.10:
@@ -343,7 +343,9 @@ void Parser::ParseOpenACCCacheVarList() {
     if (!FirstArray)
       ExpectAndConsume(tok::comma);
     FirstArray = false;
-    ParseOpenACCCacheVar();
+    if (ParseOpenACCCacheVar())
+      SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma,
+                StopBeforeMatch);
   }
 }
 
diff --git a/clang/test/ParserOpenACC/parse-cache-construct.c 
b/clang/test/ParserOpenACC/parse-cache-construct.c
index 5c0d363449e99..10976627ca95c 100644
--- a/clang/test/ParserOpenACC/parse-cache-construct.c
+++ b/clang/test/ParserOpenACC/parse-cache-construct.c
@@ -6,47 +6,46 @@ void func() {
   char *ArrayPtr = getArrayPtr();
   int *readonly;
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{expected '('}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // 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 cache clause list
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache()
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache() clause-list
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+3{{expected ')'}}
     // expected-note@+2{{to match this '('}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+5{{use of undeclared identifier 'invalid'}}
-    // expected-error@+4{{expected '['}}
+  for (int i = 0; i < 10; ++i) {
+    // expected-error@+4{{use of undeclared identifier 'invalid'}}
     // expected-error@+3{{expected ')'}}
     // expected-note@+2{{to match this '('}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(invalid
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+4{{expected '['}}
     // expected-error@+3{{expected ')'}}
     // expected-note@+2{{to match this '('}}
@@ -54,122 +53,111 @@ void func() {
     #pragma acc cache(ArrayPtr
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+3{{use of undeclared identifier 'invalid'}}
-    // expected-error@+2{{expected '['}}
+  for (int i = 0; i < 10; ++i) {
+    // expected-error@+2{{use of undeclared identifier 'invalid'}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(invalid)
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{expected '['}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(ArrayPtr)
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+6{{expected expression}}
-    // expected-error@+5{{expected ']'}}
-    // expected-note@+4{{to match this '['}}
+  for (int i = 0; i < 10; ++i) {
+    // 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 cache(ArrayPtr[
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+4{{expected expression}}
-    // expected-error@+3{{expected ']'}}
-    // expected-note@+2{{to match this '['}}
+  for (int i = 0; i < 10; ++i) {
+    // expected-error@+2{{expected expression}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(ArrayPtr[, 5)
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+4{{expected expression}}
-    // expected-error@+3{{expected ']'}}
-    // expected-note@+2{{to match this '['}}
+  for (int i = 0; i < 10; ++i) {
+    // expected-error@+2{{expected expression}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(Array[)
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(Array[*readonly])
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+6{{expected expression}}
-    // expected-error@+5{{expected ']'}}
-    // expected-note@+4{{to match this '['}}
+  for (int i = 0; i < 10; ++i) {
+    // 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 cache(Array[*readonly:
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{expected '['}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly)
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{expected '['}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr)
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{expected expression}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5:])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5:*readonly])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{expected '['}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5:*readonly], Array)
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5:*readonly], Array[*readonly:3])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5 + i:*readonly], Array[*readonly + 
i:3])
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+5{{expected identifier}}
-    // expected-error@+4{{expected '['}}
+  for (int i = 0; i < 10; ++i) {
+    // expected-error@+4{{expected identifier}}
     // expected-error@+3{{expected ')'}}
     // expected-note@+2{{to match this '('}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5:*readonly],
   }
 
-  for (int i = 0; i  < 10; ++i) {
-    // expected-error@+3{{expected identifier}}
-    // expected-error@+2{{expected '['}}
+  for (int i = 0; i < 10; ++i) {
+    // expected-error@+2{{expected identifier}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5:*readonly],)
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+2{{left operand of comma operator has no effect}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5,6:*readonly])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+2{{left operand of comma operator has no effect}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(readonly:ArrayPtr[5:3, *readonly], ArrayPtr[0])
diff --git a/clang/test/ParserOpenACC/parse-cache-construct.cpp 
b/clang/test/ParserOpenACC/parse-cache-construct.cpp
index 68e25e1c8321f..3b2230cabae32 100644
--- a/clang/test/ParserOpenACC/parse-cache-construct.cpp
+++ b/clang/test/ParserOpenACC/parse-cache-construct.cpp
@@ -8,33 +8,33 @@ char *getArrayPtr();
 template<typename T, int I>
 void func() {
   char *ArrayPtr = getArrayPtr();
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(ArrayPtr[T::value + I:I + 5], T::array[(i + T::value, 
5): 6])
   }
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(NS::NSArray[NS::NSInt])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(NS::NSArray[NS::NSInt : NS::NSInt])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{use of undeclared identifier 'NSArray'; did you mean 
'NS::NSArray'}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(NSArray[NS::NSInt : NS::NSInt])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 
'NS::NSInt'}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(NS::NSArray[NSInt : NS::NSInt])
   }
 
-  for (int i = 0; i  < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     // expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 
'NS::NSInt'}}
     // expected-warning@+1{{OpenACC directives not yet implemented, pragma 
ignored}}
     #pragma acc cache(NS::NSArray[NS::NSInt : NSInt])

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to