[clang] [OpenACC] Implement Sema work for OpenACC Clauses (PR #87821)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 8 08:18:28 PDT 2024


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

>From ca5f957bb002d79997e630cdf1aaad5703ea2ba4 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 5 Apr 2024 10:53:47 -0700
Subject: [PATCH 1/5] [OpenACC] Implement Sema work for OpenACC Clauses

Now that we have AST nodes for OpenACC Clauses, this patch adds their
creation to Sema and makes the Parser call all the required functions.
This also redoes TreeTransform to work with the clauses/make sure they
are transformed.

Much of this is NFC, since there is no clause we can test this behavior
with.  However, there IS one noticable change; we are now no longer
diagnosing that a clause is 'not implemented' unless it there was no
errors parsing its parameters.  This is because it cleans up how we
create and diagnose clauses.
---
 .../clang/Basic/DiagnosticSemaKinds.td        |   2 +
 clang/include/clang/Parse/Parser.h            |  34 +-
 clang/include/clang/Sema/SemaOpenACC.h        |  39 +-
 clang/lib/Parse/ParseOpenACC.cpp              | 142 +++--
 clang/lib/Sema/SemaOpenACC.cpp                |  69 ++-
 clang/lib/Sema/TreeTransform.h                |  79 ++-
 clang/test/ParserOpenACC/parse-clauses.c      | 573 +++++++-----------
 clang/test/ParserOpenACC/parse-clauses.cpp    |   9 +-
 clang/test/ParserOpenACC/parse-wait-clause.c  | 102 ++--
 9 files changed, 540 insertions(+), 509 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index df57f5e6ce11ba..238931770da3a2 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12252,6 +12252,8 @@ def warn_acc_clause_unimplemented
 def err_acc_construct_appertainment
     : Error<"OpenACC construct '%0' cannot be used here; it can only "
             "be used in a statement context">;
+def err_acc_clause_appertainment
+    : Error<"OpenACC '%1' clause not valid on '%0' directive">;
 def err_acc_branch_in_out_compute_construct
     : Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 "
             "OpenACC Compute Construct">;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 580bf2a5d79df5..8bc929b1dfe4bb 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -41,6 +41,7 @@ namespace clang {
   class InMessageExpressionRAIIObject;
   class PoisonSEHIdentifiersRAIIObject;
   class OMPClause;
+  class OpenACCClause;
   class ObjCTypeParamList;
   struct OMPTraitProperty;
   struct OMPTraitSelector;
@@ -3594,11 +3595,26 @@ class Parser : public CodeCompletionHandler {
     OpenACCDirectiveKind DirKind;
     SourceLocation StartLoc;
     SourceLocation EndLoc;
-    // TODO OpenACC: Add Clause list here once we have a type for that.
+    SmallVector<OpenACCClause *> Clauses;
     // TODO OpenACC: As we implement support for the Atomic, Routine, Cache, and
     // Wait constructs, we likely want to put that information in here as well.
   };
 
+  /// Represents the 'error' state of parsing an OpenACC Clause, and stores
+  /// whether we can continue parsing, or should give up on the directive.
+  enum class OpenACCParseCanContinue { Cannot = 0, Can = 1 };
+
+  /// A type to represent the state of parsing an OpenACC Clause. Situations
+  /// that result in an OpenACCClause pointer are a success and can continue
+  /// parsing, however some other situations can also continue.
+  /// FIXME: This is better represented as a std::expected when we get C++23.
+  using OpenACCClauseParseResult =
+      llvm::PointerIntPair<OpenACCClause *, 1, OpenACCParseCanContinue>;
+
+  OpenACCClauseParseResult OpenACCCanContinue();
+  OpenACCClauseParseResult OpenACCCannotContinue();
+  OpenACCClauseParseResult OpenACCSuccess(OpenACCClause *Clause);
+
   /// Parses the OpenACC directive (the entire pragma) including the clause
   /// list, but does not produce the main AST node.
   OpenACCDirectiveParseInfo ParseOpenACCDirective();
@@ -3613,12 +3629,18 @@ class Parser : public CodeCompletionHandler {
   bool ParseOpenACCClauseVarList(OpenACCClauseKind Kind);
   /// Parses any parameters for an OpenACC Clause, including required/optional
   /// parens.
-  bool ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
-                                OpenACCClauseKind Kind);
-  /// Parses a single clause in a clause-list for OpenACC.
-  bool ParseOpenACCClause(OpenACCDirectiveKind DirKind);
+  OpenACCClauseParseResult
+  ParseOpenACCClauseParams(ArrayRef<const OpenACCClause *> ExistingClauses,
+                           OpenACCDirectiveKind DirKind, OpenACCClauseKind Kind,
+                           SourceLocation ClauseLoc);
+  /// Parses a single clause in a clause-list for OpenACC. Returns nullptr on
+  /// error.
+  OpenACCClauseParseResult
+  ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
+                     OpenACCDirectiveKind DirKind);
   /// Parses the clause-list for an OpenACC directive.
-  void ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
+  SmallVector<OpenACCClause *>
+  ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
   bool ParseOpenACCWaitArgument();
   /// Parses the clause of the 'bind' argument, which can be a string literal or
   /// an ID expression.
diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index 7f50d7889ad79b..7eaf03f5be7bd8 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -28,6 +28,37 @@ class Sema;
 
 class SemaOpenACC {
 public:
+  /// A type to represent all the data for an OpenACC Clause that has been
+  /// parsed, but not yet created/semantically analyzed. This is effectively a
+  /// discriminated union on the 'Clause Kind', with all of the individual
+  /// clause details stored in a std::variant.
+  class OpenACCParsedClause {
+    OpenACCDirectiveKind DirKind;
+    OpenACCClauseKind ClauseKind;
+    SourceRange ClauseRange;
+    SourceLocation LParenLoc;
+
+    // TODO OpenACC: Add variant here to store details of individual clauses.
+
+  public:
+    OpenACCParsedClause(OpenACCDirectiveKind DirKind,
+                        OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
+        : DirKind(DirKind), ClauseKind(ClauseKind), ClauseRange(BeginLoc, {}) {}
+
+    OpenACCDirectiveKind getDirectiveKind() const { return DirKind; }
+
+    OpenACCClauseKind getClauseKind() const { return ClauseKind; }
+
+    SourceLocation getBeginLoc() const { return ClauseRange.getBegin(); }
+
+    SourceLocation getLParenLoc() const { return LParenLoc; }
+
+    SourceLocation getEndLoc() const { return ClauseRange.getEnd(); }
+
+    void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
+    void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
+  };
+
   SemaOpenACC(Sema &S);
 
   ASTContext &getASTContext() const;
@@ -37,7 +68,8 @@ class SemaOpenACC {
   Sema &SemaRef;
 
   /// Called after parsing an OpenACC Clause so that it can be checked.
-  bool ActOnClause(OpenACCClauseKind ClauseKind, SourceLocation StartLoc);
+  OpenACCClause *ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
+                             OpenACCParsedClause &Clause);
 
   /// Called after the construct has been parsed, but clauses haven't been
   /// parsed.  This allows us to diagnose not-implemented, as well as set up any
@@ -63,7 +95,10 @@ class SemaOpenACC {
   /// declaration group or associated statement.
   StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K,
                                    SourceLocation StartLoc,
-                                   SourceLocation EndLoc, StmtResult AssocStmt);
+                                   SourceLocation EndLoc,
+                                   MutableArrayRef<OpenACCClause *> Clauses,
+                                   StmtResult AssocStmt);
+
   /// Called after the directive has been completely parsed, including the
   /// declaration group or associated statement.
   DeclGroupRef ActOnEndDeclDirective();
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 07dd2ba0106a4e..374984735556d8 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/AST/OpenACCClause.h"
 #include "clang/Basic/OpenACCKinds.h"
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/Parser.h"
@@ -582,12 +583,26 @@ unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) {
 
 } // namespace
 
+Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
+  return {nullptr, OpenACCParseCanContinue::Can};
+}
+
+Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
+  return {nullptr, OpenACCParseCanContinue::Cannot};
+}
+
+Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {
+  return {Clause, OpenACCParseCanContinue::Can};
+}
+
 // OpenACC 3.3, section 1.7:
 // To simplify the specification and convey appropriate constraint information,
 // a pqr-list is a comma-separated list of pdr items. The one exception is a
 // clause-list, which is a list of one or more clauses optionally separated by
 // commas.
-void Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
+SmallVector<OpenACCClause *>
+Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
+  SmallVector<OpenACCClause *> Clauses;
   bool FirstClause = true;
   while (getCurToken().isNot(tok::annot_pragma_openacc_end)) {
     // Comma is optional in a clause-list.
@@ -595,13 +610,17 @@ void Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
       ConsumeToken();
     FirstClause = false;
 
-    // Recovering from a bad clause is really difficult, so we just give up on
-    // error.
-    if (ParseOpenACCClause(DirKind)) {
+    OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind);
+    if (OpenACCClause *Clause = Result.getPointer()) {
+      Clauses.push_back(Clause);
+    } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) {
+      // Recovering from a bad clause is really difficult, so we just give up on
+      // error.
       SkipUntilEndOfDirective(*this);
-      return;
+      return Clauses;
     }
   }
+  return Clauses;
 }
 
 ExprResult Parser::ParseOpenACCIntExpr() {
@@ -762,42 +781,48 @@ bool Parser::ParseOpenACCGangArgList() {
 // really have its owner grammar and each individual one has its own definition.
 // However, they all are named with a single-identifier (or auto/default!)
 // token, followed in some cases by either braces or parens.
-bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) {
+Parser::OpenACCClauseParseResult
+Parser::ParseOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
+                           OpenACCDirectiveKind DirKind) {
   // A number of clause names are actually keywords, so accept a keyword that
   // can be converted to a name.
   if (expectIdentifierOrKeyword(*this))
-    return true;
+    return OpenACCCannotContinue();
 
   OpenACCClauseKind Kind = getOpenACCClauseKind(getCurToken());
 
-  if (Kind == OpenACCClauseKind::Invalid)
-    return Diag(getCurToken(), diag::err_acc_invalid_clause)
-           << getCurToken().getIdentifierInfo();
+  if (Kind == OpenACCClauseKind::Invalid) {
+    Diag(getCurToken(), diag::err_acc_invalid_clause)
+        << getCurToken().getIdentifierInfo();
+    return OpenACCCannotContinue();
+  }
 
   // Consume the clause name.
   SourceLocation ClauseLoc = ConsumeToken();
 
-  bool Result = ParseOpenACCClauseParams(DirKind, Kind);
-  getActions().OpenACC().ActOnClause(Kind, ClauseLoc);
-  return Result;
+  return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);
 }
 
-bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
-                                      OpenACCClauseKind Kind) {
+Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
+    ArrayRef<const OpenACCClause *> ExistingClauses,
+    OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind,
+    SourceLocation ClauseLoc) {
   BalancedDelimiterTracker Parens(*this, tok::l_paren,
                                   tok::annot_pragma_openacc_end);
+  SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc);
 
-  if (ClauseHasRequiredParens(DirKind, Kind)) {
+  if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
+    ParsedClause.setLParenLoc(getCurToken().getLocation());
     if (Parens.expectAndConsume()) {
       // We are missing a paren, so assume that the person just forgot the
       // parameter.  Return 'false' so we try to continue on and parse the next
       // clause.
       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
                 Parser::StopBeforeMatch);
-      return false;
+      return OpenACCCanContinue();
     }
 
-    switch (Kind) {
+    switch (ClauseKind) {
     case OpenACCClauseKind::Default: {
       Token DefKindTok = getCurToken();
 
@@ -818,34 +843,34 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
       // this clause list.
       if (CondExpr.isInvalid()) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     }
     case OpenACCClauseKind::CopyIn:
       tryParseAndConsumeSpecialTokenKind(
-          *this, OpenACCSpecialTokenKind::ReadOnly, Kind);
-      if (ParseOpenACCClauseVarList(Kind)) {
+          *this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind);
+      if (ParseOpenACCClauseVarList(ClauseKind)) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     case OpenACCClauseKind::Create:
     case OpenACCClauseKind::CopyOut:
       tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Zero,
-                                         Kind);
-      if (ParseOpenACCClauseVarList(Kind)) {
+                                         ClauseKind);
+      if (ParseOpenACCClauseVarList(ClauseKind)) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     case OpenACCClauseKind::Reduction:
       // If we're missing a clause-kind (or it is invalid), see if we can parse
       // the var-list anyway.
       ParseReductionOperator(*this);
-      if (ParseOpenACCClauseVarList(Kind)) {
+      if (ParseOpenACCClauseVarList(ClauseKind)) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     case OpenACCClauseKind::Self:
@@ -868,19 +893,19 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
     case OpenACCClauseKind::Present:
     case OpenACCClauseKind::Private:
     case OpenACCClauseKind::UseDevice:
-      if (ParseOpenACCClauseVarList(Kind)) {
+      if (ParseOpenACCClauseVarList(ClauseKind)) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     case OpenACCClauseKind::Collapse: {
       tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Force,
-                                         Kind);
+                                         ClauseKind);
       ExprResult NumLoops =
           getActions().CorrectDelayedTyposInExpr(ParseConstantExpression());
       if (NumLoops.isInvalid()) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     }
@@ -888,7 +913,7 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
       ExprResult BindArg = ParseOpenACCBindClauseArgument();
       if (BindArg.isInvalid()) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     }
@@ -900,7 +925,7 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
       ExprResult IntExpr = ParseOpenACCIntExpr();
       if (IntExpr.isInvalid()) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     }
@@ -912,23 +937,28 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
         ConsumeToken();
       } else if (ParseOpenACCDeviceTypeList()) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     case OpenACCClauseKind::Tile:
       if (ParseOpenACCSizeExprList()) {
         Parens.skipToEnd();
-        return false;
+        return OpenACCCanContinue();
       }
       break;
     default:
       llvm_unreachable("Not a required parens type?");
     }
 
-    return Parens.consumeClose();
-  } else if (ClauseHasOptionalParens(DirKind, Kind)) {
+    ParsedClause.setEndLoc(getCurToken().getLocation());
+
+    if (Parens.consumeClose())
+      return OpenACCCannotContinue();
+
+  } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
+    ParsedClause.setLParenLoc(getCurToken().getLocation());
     if (!Parens.consumeOpen()) {
-      switch (Kind) {
+      switch (ClauseKind) {
       case OpenACCClauseKind::Self: {
         assert(DirKind != OpenACCDirectiveKind::Update);
         ExprResult CondExpr = ParseOpenACCConditionalExpr(*this);
@@ -936,21 +966,22 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
         // this clause list.
         if (CondExpr.isInvalid()) {
           Parens.skipToEnd();
-          return false;
+          return OpenACCCanContinue();
         }
         break;
       }
       case OpenACCClauseKind::Vector:
       case OpenACCClauseKind::Worker: {
         tryParseAndConsumeSpecialTokenKind(*this,
-                                           Kind == OpenACCClauseKind::Vector
+                                           ClauseKind ==
+                                                   OpenACCClauseKind::Vector
                                                ? OpenACCSpecialTokenKind::Length
                                                : OpenACCSpecialTokenKind::Num,
-                                           Kind);
+                                           ClauseKind);
         ExprResult IntExpr = ParseOpenACCIntExpr();
         if (IntExpr.isInvalid()) {
           Parens.skipToEnd();
-          return false;
+          return OpenACCCanContinue();
         }
         break;
       }
@@ -958,29 +989,32 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
         ExprResult AsyncArg = ParseOpenACCAsyncArgument();
         if (AsyncArg.isInvalid()) {
           Parens.skipToEnd();
-          return false;
+          return OpenACCCanContinue();
         }
         break;
       }
       case OpenACCClauseKind::Gang:
         if (ParseOpenACCGangArgList()) {
           Parens.skipToEnd();
-          return false;
+          return OpenACCCanContinue();
         }
         break;
       case OpenACCClauseKind::Wait:
         if (ParseOpenACCWaitArgument()) {
           Parens.skipToEnd();
-          return false;
+          return OpenACCCanContinue();
         }
         break;
       default:
         llvm_unreachable("Not an optional parens type?");
       }
-      Parens.consumeClose();
+      ParsedClause.setEndLoc(getCurToken().getLocation());
+      if (Parens.consumeClose())
+        return OpenACCCannotContinue();
     }
   }
-  return false;
+  return OpenACCSuccess(
+      Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause));
 }
 
 /// OpenACC 3.3 section 2.16:
@@ -1204,15 +1238,16 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
     Diag(Tok, diag::err_expected) << tok::l_paren;
   }
 
-  // Parses the list of clauses, if present.
-  ParseOpenACCClauseList(DirKind);
+  // Parses the list of clauses, if present, plus set up return value.
+  OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, SourceLocation{},
+                                      ParseOpenACCClauseList(DirKind)};
 
   assert(Tok.is(tok::annot_pragma_openacc_end) &&
          "Didn't parse all OpenACC Clauses");
-  SourceLocation EndLoc = ConsumeAnnotationToken();
-  assert(EndLoc.isValid());
+  ParseInfo.EndLoc = ConsumeAnnotationToken();
+  assert(ParseInfo.EndLoc.isValid());
 
-  return OpenACCDirectiveParseInfo{DirKind, StartLoc, EndLoc};
+  return ParseInfo;
 }
 
 // Parse OpenACC directive on a declaration.
@@ -1255,5 +1290,6 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
   }
 
   return getActions().OpenACC().ActOnEndStmtDirective(
-      DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, AssocStmt);
+      DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, DirInfo.Clauses,
+      AssocStmt);
 }
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 86ffa5ad74c130..cd91d4fb2b7925 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -37,6 +37,32 @@ bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
   }
   return false;
 }
+
+bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
+                                OpenACCClauseKind ClauseKind) {
+  switch (ClauseKind) {
+    // FIXME: For each clause as we implement them, we can add the
+    // 'legalization' list here.
+  default:
+    // Do nothing so we can go to the 'unimplemented' diagnostic instead.
+    return true;
+  }
+  llvm_unreachable("Invalid clause kind");
+}
+
+/// Destruct and deallocate any clauses that aren't going to be used because
+/// they don't have a Construct to attach to.
+void DestroyUnusedClauses(ASTContext &Ctx,
+                          MutableArrayRef<OpenACCClause *> Clauses) {
+  auto *Itr = Clauses.begin();
+  auto *End = Clauses.end();
+
+  for (; Itr != End; ++Itr) {
+    (*Itr)->~OpenACCClause();
+    Ctx.Deallocate(*Itr);
+    *Itr = nullptr;
+  }
+}
 } // namespace
 
 SemaOpenACC::SemaOpenACC(Sema &S) : SemaRef(S) {}
@@ -45,17 +71,28 @@ ASTContext &SemaOpenACC::getASTContext() const { return SemaRef.Context; }
 DiagnosticsEngine &SemaOpenACC::getDiagnostics() const { return SemaRef.Diags; }
 const LangOptions &SemaOpenACC::getLangOpts() const { return SemaRef.LangOpts; }
 
-bool SemaOpenACC::ActOnClause(OpenACCClauseKind ClauseKind,
-                              SourceLocation StartLoc) {
-  if (ClauseKind == OpenACCClauseKind::Invalid)
-    return false;
-  // For now just diagnose that it is unsupported and leave the parsing to do
-  // whatever it can do. This function will eventually need to start returning
-  // some sort of Clause AST type, but for now just return true/false based on
-  // success.
-  return SemaRef.Diag(StartLoc, diag::warn_acc_clause_unimplemented)
-         << ClauseKind;
+OpenACCClause *
+SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
+                         OpenACCParsedClause &Clause) {
+  if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
+    return nullptr;
+
+  // Diagnose that we don't support this clause on this directive.
+  if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
+                                  Clause.getClauseKind())) {
+    SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
+        << Clause.getDirectiveKind() << Clause.getClauseKind();
+    return nullptr;
+  }
+
+  // TODO OpenACC: Switch over the clauses we implement here and 'create'
+  // them.
+
+  SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
+      << Clause.getClauseKind();
+  return nullptr;
 }
+
 void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
                                  SourceLocation StartLoc) {
   switch (K) {
@@ -82,22 +119,22 @@ bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K,
   return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
 }
 
-StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
-                                              SourceLocation StartLoc,
-                                              SourceLocation EndLoc,
-                                              StmtResult AssocStmt) {
+StmtResult SemaOpenACC::ActOnEndStmtDirective(
+    OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation EndLoc,
+    MutableArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
   switch (K) {
   default:
+    DestroyUnusedClauses(getASTContext(), Clauses);
     return StmtEmpty();
   case OpenACCDirectiveKind::Invalid:
+    DestroyUnusedClauses(getASTContext(), Clauses);
     return StmtError();
   case OpenACCDirectiveKind::Parallel:
   case OpenACCDirectiveKind::Serial:
   case OpenACCDirectiveKind::Kernels:
     // TODO OpenACC: Add clauses to the construct here.
     return OpenACCComputeConstruct::Create(
-        getASTContext(), K, StartLoc, EndLoc,
-        /*Clauses=*/std::nullopt,
+        getASTContext(), K, StartLoc, EndLoc, Clauses,
         AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
   }
   llvm_unreachable("Unhandled case in directive handling?");
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7df352c24e8648..374d02009516cf 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4003,20 +4003,11 @@ class TreeTransform {
     return getSema().CreateRecoveryExpr(BeginLoc, EndLoc, SubExprs, Type);
   }
 
-  StmtResult RebuildOpenACCComputeConstruct(OpenACCDirectiveKind K,
-                                            SourceLocation BeginLoc,
-                                            SourceLocation EndLoc,
-                                            StmtResult StrBlock) {
-    getSema().OpenACC().ActOnConstruct(K, BeginLoc);
-
-    // TODO OpenACC: Include clauses.
-    if (getSema().OpenACC().ActOnStartStmtDirective(K, BeginLoc))
-      return StmtError();
-
-    StrBlock = getSema().OpenACC().ActOnAssociatedStmt(K, StrBlock);
-
+  StmtResult RebuildOpenACCComputeConstruct(
+      OpenACCDirectiveKind K, SourceLocation BeginLoc, SourceLocation EndLoc,
+      MutableArrayRef<OpenACCClause *> Clauses, StmtResult StrBlock) {
     return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, EndLoc,
-                                                     StrBlock);
+                                                     Clauses, StrBlock);
   }
 
 private:
@@ -4037,6 +4028,15 @@ class TreeTransform {
   QualType TransformDependentNameType(TypeLocBuilder &TLB,
                                       DependentNameTypeLoc TL,
                                       bool DeducibleTSTContext);
+
+  llvm::SmallVector<OpenACCClause *>
+  TransformOpenACCClauseList(OpenACCDirectiveKind DirKind,
+                             ArrayRef<const OpenACCClause *> OldClauses);
+
+  OpenACCClause *
+  TransformOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
+                         OpenACCDirectiveKind DirKind,
+                         const OpenACCClause *OldClause);
 };
 
 template <typename Derived>
@@ -11077,16 +11077,65 @@ OMPClause *TreeTransform<Derived>::TransformOMPXBareClause(OMPXBareClause *C) {
 //===----------------------------------------------------------------------===//
 // OpenACC transformation
 //===----------------------------------------------------------------------===//
+template <typename Derived>
+OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(
+    ArrayRef<const OpenACCClause *> ExistingClauses,
+    OpenACCDirectiveKind DirKind, const OpenACCClause *OldClause) {
+
+  SemaOpenACC::OpenACCParsedClause ParsedClause(
+      DirKind, OldClause->getClauseKind(), OldClause->getBeginLoc());
+  ParsedClause.setEndLoc(OldClause->getEndLoc());
+
+  if (const auto *WithParms = dyn_cast<OpenACCClauseWithParams>(OldClause))
+    ParsedClause.setLParenLoc(WithParms->getLParenLoc());
+
+  switch (OldClause->getClauseKind()) {
+    // TODO OpenACC: Transform individual clauses, and set their info in
+    // ParsedClause.
+  default:
+    assert(false && "Unhandled OpenACC clause in TreeTransform");
+    return nullptr;
+  }
+
+  return getSema().OpenACC().ActOnClause(ExistingClauses, ParsedClause);
+}
+
+template <typename Derived>
+llvm::SmallVector<OpenACCClause *>
+TreeTransform<Derived>::TransformOpenACCClauseList(
+    OpenACCDirectiveKind DirKind, ArrayRef<const OpenACCClause *> OldClauses) {
+  llvm::SmallVector<OpenACCClause *> TransformedClauses;
+  for (const auto *Clause : OldClauses) {
+    if (OpenACCClause *TransformedClause = getDerived().TransformOpenACCClause(
+            TransformedClauses, DirKind, Clause))
+      TransformedClauses.push_back(TransformedClause);
+  }
+  return TransformedClauses;
+}
+
 template <typename Derived>
 StmtResult TreeTransform<Derived>::TransformOpenACCComputeConstruct(
     OpenACCComputeConstruct *C) {
-  // TODO OpenACC: Transform clauses.
+  getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc());
+  // FIXME: When implementing this for constructs that can take arguments, we
+  // should do Sema for them here.
+
+  if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),
+                                                  C->getBeginLoc()))
+    return StmtError();
+
+  llvm::SmallVector<OpenACCClause *> TransformedClauses =
+      getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
+                                              C->clauses());
 
   // Transform Structured Block.
   StmtResult StrBlock = getDerived().TransformStmt(C->getStructuredBlock());
+  StrBlock =
+      getSema().OpenACC().ActOnAssociatedStmt(C->getDirectiveKind(), StrBlock);
 
   return getDerived().RebuildOpenACCComputeConstruct(
-      C->getDirectiveKind(), C->getBeginLoc(), C->getEndLoc(), StrBlock);
+      C->getDirectiveKind(), C->getBeginLoc(), C->getEndLoc(),
+      TransformedClauses, StrBlock);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index a82c3662f2ad9e..b58b332ad3245c 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -86,27 +86,23 @@ void func() {
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop seq,
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'collapse' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop collapse
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'collapse' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop collapse()
   for(;;){}
 
-  // expected-error at +4{{invalid tag 'unknown' on 'collapse' clause}}
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'collapse' not yet implemented, clause ignored}}
+  // expected-error at +3{{invalid tag 'unknown' on 'collapse' clause}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop collapse(unknown:)
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'collapse' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop collapse(force:)
   for(;;){}
@@ -127,62 +123,53 @@ void func() {
 #pragma acc loop collapse(5)
   for(;;){}
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'collapse' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop collapse(5, 6)
   for(;;){}
 }
 
 void DefaultClause() {
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop default
   for(;;){}
 
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc serial default seq
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial default, seq
   for(;;){}
 
-  // expected-error at +4{{expected identifier}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected identifier}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial default(
   for(;;){}
 
-  // expected-error at +4{{invalid value for 'default' clause; expected 'present' or 'none'}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +3{{invalid value for 'default' clause; expected 'present' or 'none'}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial default( seq
   for(;;){}
 
-  // expected-error at +4{{expected identifier}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected identifier}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial default(, seq
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-error at +2{{expected identifier}}
-  // expected-warning at +1{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
+  // expected-error at +1{{expected identifier}}
 #pragma acc serial default)
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-error at +2{{expected identifier}}
-  // expected-warning at +1{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
+  // expected-error at +1{{expected identifier}}
 #pragma acc serial default), seq
   for(;;){}
 
@@ -231,87 +218,73 @@ void DefaultClause() {
 }
 
 void IfClause() {
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop if
   for(;;){}
 
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc serial if seq
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if, seq
   for(;;){}
 
-  // expected-error at +4{{expected expression}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial if(
   for(;;){}
 
-  // expected-error at +4{{use of undeclared identifier 'seq'}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +3{{use of undeclared identifier 'seq'}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial if( seq
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{use of undeclared identifier 'seq'}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{use of undeclared identifier 'seq'}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial if(, seq
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-error at +2{{expected identifier}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
+  // expected-error at +1{{expected identifier}}
 #pragma acc serial if)
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-error at +2{{expected identifier}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
+  // expected-error at +1{{expected identifier}}
 #pragma acc serial if) seq
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-error at +2{{expected identifier}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
+  // expected-error at +1{{expected identifier}}
 #pragma acc serial if), seq
   for(;;){}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
 #pragma acc serial if()
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if() seq
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if(), seq
   for(;;){}
 
-  // expected-error at +2{{use of undeclared identifier 'invalid_expr'}}
-  // expected-warning at +1{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +1{{use of undeclared identifier 'invalid_expr'}}
 #pragma acc serial if(invalid_expr)
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if() seq
   for(;;){}
@@ -340,27 +313,24 @@ void SelfClause() {
 #pragma acc serial loop self, seq
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop self(
   for(;;){}
 
-  // expected-error at +5{{use of undeclared identifier 'seq'}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +4{{use of undeclared identifier 'seq'}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop self( seq
   for(;;){}
 
-  // expected-error at +6{{expected expression}}
-  // expected-error at +5{{use of undeclared identifier 'seq'}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +5{{expected expression}}
+  // expected-error at +4{{use of undeclared identifier 'seq'}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop self(, seq
   for(;;){}
@@ -384,23 +354,20 @@ void SelfClause() {
   for(;;){}
 
 
-  // expected-error at +4{{expected expression}}
-  // expected-warning at +3{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
   // expected-warning at +2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop self(), seq
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
   // expected-error at +4{{expected expression}}
-  // expected-warning at +3{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
   // expected-warning at +2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop self(,), seq
   for(;;){}
 
-  // expected-error at +4{{use of undeclared identifier 'invalid_expr'}}
-  // expected-warning at +3{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +3{{use of undeclared identifier 'invalid_expr'}}
   // expected-warning at +2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop self(invalid_expr), seq
@@ -408,16 +375,14 @@ void SelfClause() {
 
   int i, j;
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial self(i > j
   for(;;){}
 
-  // expected-error at +4{{use of undeclared identifier 'seq'}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +3{{use of undeclared identifier 'seq'}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial self(i > j, seq
   for(;;){}
 
@@ -448,14 +413,12 @@ struct HasMembersArray {
 void SelfUpdate() {
   struct Members s;
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'update' not yet implemented, pragma ignored}}
 #pragma acc update self
   for(;;){}
 
-  // expected-error at +4{{use of undeclared identifier 'zero'}}
-  // expected-warning at +3{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error at +3{{use of undeclared identifier 'zero'}}
   // expected-warning at +2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'update' not yet implemented, pragma ignored}}
 #pragma acc update self(zero : s.array[s.value : 5], s.value), seq
@@ -469,50 +432,42 @@ void SelfUpdate() {
 }
 
 void VarListClauses() {
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc serial copy
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy, seq
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-error at +2{{expected identifier}}
-  // expected-warning at +1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
+  // expected-error at +1{{expected identifier}}
 #pragma acc serial copy)
   for(;;){}
 
-  // expected-error at +3{{expected '('}}
-  // expected-error at +2{{expected identifier}}
-  // expected-warning at +1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
+  // expected-error at +1{{expected identifier}}
 #pragma acc serial copy), seq
   for(;;){}
 
-  // expected-error at +4{{expected expression}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial copy(
   for(;;){}
 
-  // expected-error at +4{{expected expression}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc serial copy(, seq
   for(;;){}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
 #pragma acc serial copy()
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(), seq
   for(;;){}
@@ -552,28 +507,24 @@ void VarListClauses() {
 #pragma acc serial copy(HasMem.MemArr[1:3].array[1:2]), seq
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[:]), seq
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[::]), seq
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ']'}}
-  // expected-note at +3{{to match this '['}}
-  // expected-warning at +2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ']'}}
+  // expected-note at +2{{to match this '['}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[: :]), seq
   for(;;){}
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[3:]), seq
   for(;;){}
@@ -753,8 +704,7 @@ void VarListClauses() {
 #pragma acc serial copyout(zero : s.array[s.value : 5], s.value), seq
   for(;;){}
 
-  // expected-error at +3{{use of undeclared identifier 'zero'}}
-  // expected-warning at +2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'zero'}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(zero s.array[s.value : 5], s.value), seq
   for(;;){}
@@ -777,8 +727,7 @@ void VarListClauses() {
 #pragma acc serial copyout(invalid:s.array[s.value : 5], s.value), seq
   for(;;){}
 
-  // expected-error at +3{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'invalid'}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(invalid s.array[s.value : 5], s.value), seq
   for(;;){}
@@ -804,8 +753,7 @@ void VarListClauses() {
 #pragma acc serial create(zero : s.array[s.value : 5], s.value), seq
   for(;;){}
 
-  // expected-error at +3{{use of undeclared identifier 'zero'}}
-  // expected-warning at +2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'zero'}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(zero s.array[s.value : 5], s.value), seq
   for(;;){}
@@ -828,8 +776,7 @@ void VarListClauses() {
 #pragma acc serial create(invalid:s.array[s.value : 5], s.value), seq
   for(;;){}
 
-  // expected-error at +3{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'invalid'}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(invalid s.array[s.value : 5], s.value), seq
   for(;;){}
@@ -855,8 +802,7 @@ void VarListClauses() {
 #pragma acc serial copyin(readonly : s.array[s.value : 5], s.value), seq
   for(;;){}
 
-  // expected-error at +3{{use of undeclared identifier 'readonly'}}
-  // expected-warning at +2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'readonly'}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(readonly s.array[s.value : 5], s.value), seq
   for(;;){}
@@ -879,8 +825,7 @@ void VarListClauses() {
 #pragma acc serial copyin(invalid:s.array[s.value : 5], s.value), seq
   for(;;){}
 
-  // expected-error at +3{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'invalid'}}
   // expected-warning at +1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(invalid s.array[s.value : 5], s.value), seq
   for(;;){}
@@ -888,13 +833,11 @@ void VarListClauses() {
 
 void ReductionClauseParsing() {
   char *Begin, *End;
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc serial reduction
   for(;;){}
-  // expected-error at +3{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
+  // expected-error at +2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+  // expected-error at +1{{expected expression}}
 #pragma acc serial reduction()
   for(;;){}
   // expected-error at +2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
@@ -946,24 +889,20 @@ void ReductionClauseParsing() {
 int returns_int();
 
 void IntExprParsing() {
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'vector_length' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc parallel vector_length
   {}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'vector_length' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
 #pragma acc parallel vector_length()
   {}
 
-  // expected-error at +2{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +1{{OpenACC clause 'vector_length' not yet implemented, clause ignored}}
+  // expected-error at +1{{use of undeclared identifier 'invalid'}}
 #pragma acc parallel vector_length(invalid)
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'vector_length' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel vector_length(5, 4)
   {}
 
@@ -975,24 +914,20 @@ void IntExprParsing() {
 #pragma acc parallel vector_length(returns_int())
   {}
 
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc parallel num_gangs
   {}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
 #pragma acc parallel num_gangs()
   {}
 
-  // expected-error at +2{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}}
+  // expected-error at +1{{use of undeclared identifier 'invalid'}}
 #pragma acc parallel num_gangs(invalid)
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'num_gangs' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel num_gangs(5, 4)
   {}
 
@@ -1004,24 +939,20 @@ void IntExprParsing() {
 #pragma acc parallel num_gangs(returns_int())
   {}
 
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'num_workers' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc parallel num_workers
   {}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'num_workers' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
 #pragma acc parallel num_workers()
   {}
 
-  // expected-error at +2{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +1{{OpenACC clause 'num_workers' not yet implemented, clause ignored}}
+  // expected-error at +1{{use of undeclared identifier 'invalid'}}
 #pragma acc parallel num_workers(invalid)
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'num_workers' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel num_workers(5, 4)
   {}
 
@@ -1033,24 +964,20 @@ void IntExprParsing() {
 #pragma acc parallel num_workers(returns_int())
   {}
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'device_num' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'init' not yet implemented, pragma ignored}}
 #pragma acc init device_num
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'device_num' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'init' not yet implemented, pragma ignored}}
 #pragma acc init device_num()
 
-  // expected-error at +3{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +2{{OpenACC clause 'device_num' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'invalid'}}
   // expected-warning at +1{{OpenACC construct 'init' not yet implemented, pragma ignored}}
 #pragma acc init device_num(invalid)
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'device_num' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'init' not yet implemented, pragma ignored}}
 #pragma acc init device_num(5, 4)
 
@@ -1062,24 +989,20 @@ void IntExprParsing() {
   // expected-warning at +1{{OpenACC construct 'init' not yet implemented, pragma ignored}}
 #pragma acc init device_num(returns_int())
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
 #pragma acc set default_async
 
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
 #pragma acc set default_async()
 
-  // expected-error at +3{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'invalid'}}
   // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
 #pragma acc set default_async(invalid)
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
 #pragma acc set default_async(5, 4)
 
@@ -1095,42 +1018,35 @@ void IntExprParsing() {
   // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector()
-  // expected-error at +4{{invalid tag 'invalid' on 'vector' clause}}
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
+  // expected-error at +3{{invalid tag 'invalid' on 'vector' clause}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector(invalid:)
   // expected-error at +3{{invalid tag 'invalid' on 'vector' clause}}
   // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector(invalid:5)
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector(length:)
-  // expected-error at +4{{invalid tag 'num' on 'vector' clause}}
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
+  // expected-error at +3{{invalid tag 'num' on 'vector' clause}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector(num:)
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector(5, 4)
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector(length:6,4)
-  // expected-error at +5{{invalid tag 'num' on 'vector' clause}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
+  // expected-error at +4{{invalid tag 'num' on 'vector' clause}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop vector(num:6,4)
   // expected-warning at +2{{OpenACC clause 'vector' not yet implemented, clause ignored}}
@@ -1153,42 +1069,35 @@ void IntExprParsing() {
   // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker()
-  // expected-error at +4{{invalid tag 'invalid' on 'worker' clause}}
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
+  // expected-error at +3{{invalid tag 'invalid' on 'worker' clause}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker(invalid:)
   // expected-error at +3{{invalid tag 'invalid' on 'worker' clause}}
   // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker(invalid:5)
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker(num:)
-  // expected-error at +4{{invalid tag 'length' on 'worker' clause}}
-  // expected-error at +3{{expected expression}}
-  // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
+  // expected-error at +3{{invalid tag 'length' on 'worker' clause}}
+  // expected-error at +2{{expected expression}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker(length:)
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker(5, 4)
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker(num:6,4)
-  // expected-error at +5{{invalid tag 'length' on 'worker' clause}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
+  // expected-error at +4{{invalid tag 'length' on 'worker' clause}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop worker(length:6,4)
   // expected-warning at +2{{OpenACC clause 'worker' not yet implemented, clause ignored}}
@@ -1211,25 +1120,21 @@ void IntExprParsing() {
 }
 
 void device_type() {
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc parallel device_type
   {}
-  // expected-error at +2{{expected '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected '('}}
 #pragma acc parallel dtype
   {}
 
-  // expected-error at +4{{expected identifier}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected identifier}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel device_type(
     {}
-  // expected-error at +4{{expected identifier}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected identifier}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel dtype(
   {}
 
@@ -1242,49 +1147,41 @@ void device_type() {
 #pragma acc parallel dtype()
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel device_type(*
   {}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel dtype(*
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel device_type(ident
   {}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel dtype(ident
   {}
 
-  // expected-error at +4{{expected ','}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ','}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel device_type(ident ident2
   {}
-  // expected-error at +4{{expected ','}}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ','}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel dtype(ident ident2
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel device_type(ident, ident2
   {}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel dtype(ident, ident2
   {}
 
@@ -1297,25 +1194,21 @@ void device_type() {
 #pragma acc parallel dtype(ident, ident2,)
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel device_type(*,)
   {}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel dtype(*,)
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel device_type(*,ident)
   {}
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'dtype' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel dtype(*,ident)
   {}
 
@@ -1356,19 +1249,16 @@ void AsyncArgument() {
 #pragma acc parallel async
   {}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'async' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
 #pragma acc parallel async()
   {}
 
-  // expected-error at +2{{use of undeclared identifier 'invalid'}}
-  // expected-warning at +1{{OpenACC clause 'async' not yet implemented, clause ignored}}
+  // expected-error at +1{{use of undeclared identifier 'invalid'}}
 #pragma acc parallel async(invalid)
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'async' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
 #pragma acc parallel async(4, 3)
   {}
 
@@ -1388,15 +1278,13 @@ void AsyncArgument() {
 void Tile() {
 
   int* Foo;
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'tile' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop tile
   for(;;){}
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'tile' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop tile(
   for(;;){}
@@ -1405,10 +1293,9 @@ void Tile() {
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop tile()
   for(;;){}
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'tile' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop tile(,
   for(;;){}
@@ -1466,10 +1353,9 @@ void Gang() {
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang
   for(;;){}
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(
   for(;;){}
@@ -1552,77 +1438,67 @@ void Gang() {
 #pragma acc loop gang(static:45, 5)
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(static:45,
   for(;;){}
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(static:45
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(static:*,
   for(;;){}
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(static:*
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(45,
   for(;;){}
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(45
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(num:45,
   for(;;){}
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(num:45
   for(;;){}
 
-  // expected-error at +5{{expected expression}}
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +4{{expected expression}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(dim:45,
   for(;;){}
 
-  // expected-error at +4{{expected ')'}}
-  // expected-note at +3{{to match this '('}}
-  // expected-warning at +2{{OpenACC clause 'gang' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ')'}}
+  // expected-note at +2{{to match this '('}}
   // expected-warning at +1{{OpenACC construct 'loop' not yet implemented, pragma ignored}}
 #pragma acc loop gang(dim:45
   for(;;){}
@@ -1657,14 +1533,12 @@ void bar();
 
 // Bind Clause Parsing.
 
-  // expected-error at +3{{expected '('}}
-  // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected '('}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine bind
 void BCP1();
 
-  // expected-error at +3{{expected identifier or string literal}}
-  // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected identifier or string literal}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(BCP1) bind()
 
@@ -1677,7 +1551,6 @@ void BCP2();
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(BCP1) bind(BCP2)
 
-  // expected-error at +3{{use of undeclared identifier 'unknown_thing'}}
-  // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'unknown_thing'}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(BCP1) bind(unknown_thing)
diff --git a/clang/test/ParserOpenACC/parse-clauses.cpp b/clang/test/ParserOpenACC/parse-clauses.cpp
index 497b1c7bcd0da4..09a90726c69396 100644
--- a/clang/test/ParserOpenACC/parse-clauses.cpp
+++ b/clang/test/ParserOpenACC/parse-clauses.cpp
@@ -56,9 +56,8 @@ void function();
   // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(use) bind(NS::NSFunc)
-  // expected-error at +4{{'RecordTy' does not refer to a value}}
+  // expected-error at +3{{'RecordTy' does not refer to a value}}
   // expected-note@#RecTy{{declared here}}
-  // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(use) bind(NS::RecordTy)
   // expected-error at +4{{'Value' is a private member of 'NS::RecordTy'}}
@@ -72,8 +71,7 @@ void function();
   // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(use) bind(NS::TemplTy<int>)
-  // expected-error at +3{{no member named 'unknown' in namespace 'NS'}}
-  // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
+  // expected-error at +2{{no member named 'unknown' in namespace 'NS'}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(use) bind(NS::unknown<int>)
   // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
@@ -88,8 +86,7 @@ void function();
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(use) bind(NS::RecordTy::mem_function)
 
-  // expected-error at +3{{string literal with user-defined suffix cannot be used here}}
-  // expected-warning at +2{{OpenACC clause 'bind' not yet implemented, clause ignored}}
+  // expected-error at +2{{string literal with user-defined suffix cannot be used here}}
   // expected-warning at +1{{OpenACC construct 'routine' not yet implemented, pragma ignored}}
 #pragma acc routine(use) bind("unknown udl"_UDL)
 
diff --git a/clang/test/ParserOpenACC/parse-wait-clause.c b/clang/test/ParserOpenACC/parse-wait-clause.c
index cce050d5da9841..f3e651de458377 100644
--- a/clang/test/ParserOpenACC/parse-wait-clause.c
+++ b/clang/test/ParserOpenACC/parse-wait-clause.c
@@ -12,9 +12,8 @@ void func() {
   #pragma acc parallel wait clause-list
   {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait (
       {}
 
@@ -27,45 +26,38 @@ void func() {
   #pragma acc parallel 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 clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait (devnum:
     {}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
   #pragma acc parallel wait (devnum:)
     {}
 
-  // expected-error at +3{{expected expression}}
-  // expected-error at +2{{invalid OpenACC clause 'clause'}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
+  // expected-error at +1{{invalid OpenACC clause 'clause'}}
   #pragma acc parallel 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 clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected ':'}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait (devnum: i + j
     {}
 
-  // expected-error at +2{{expected ':'}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected ':'}}
   #pragma acc parallel wait (devnum: i + j)
     {}
 
-  // expected-error at +3{{expected ':'}}
-  // expected-error at +2{{invalid OpenACC clause 'clause'}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ':'}}
+  // expected-error at +1{{invalid OpenACC clause 'clause'}}
   #pragma acc parallel wait (devnum: i + j) clause-list
     {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait (queues:
     {}
 
@@ -78,9 +70,8 @@ void func() {
   #pragma acc parallel wait (queues:) clause-list
     {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait (devnum: i + j:queues:
     {}
 
@@ -93,27 +84,23 @@ void func() {
   #pragma acc parallel 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 clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +3{{use of undeclared identifier 'devnum'}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait (queues:devnum: i + j
     {}
 
-  // expected-error at +2{{use of undeclared identifier 'devnum'}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +1{{use of undeclared identifier 'devnum'}}
   #pragma acc parallel wait (queues:devnum: i + j)
     {}
 
-  // expected-error at +3{{use of undeclared identifier 'devnum'}}
-  // expected-error at +2{{invalid OpenACC clause 'clause'}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{use of undeclared identifier 'devnum'}}
+  // expected-error at +1{{invalid OpenACC clause 'clause'}}
   #pragma acc parallel wait (queues:devnum: i + j) clause-list
     {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait(i, j, 1+1, 3.3
     {}
 
@@ -125,34 +112,29 @@ void func() {
   #pragma acc parallel 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 clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait(,
     {}
 
-  // expected-error at +2{{expected expression}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +1{{expected expression}}
   #pragma acc parallel wait(,)
     {}
 
-  // expected-error at +3{{expected expression}}
-  // expected-error at +2{{invalid OpenACC clause 'clause'}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected expression}}
+  // expected-error at +1{{invalid OpenACC clause 'clause'}}
   #pragma acc parallel wait(,) clause-list
     {}
 
-  // expected-error at +3{{expected ')'}}
-  // expected-note at +2{{to match this '('}}
-  // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel 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 clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +3{{expected expression}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait(queues:i, j, 1+1, 3.3,
     {}
 
@@ -165,9 +147,8 @@ void func() {
   #pragma acc parallel 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 clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait(devnum:3:i, j, 1+1, 3.3
     {}
   // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}
@@ -178,9 +159,8 @@ void func() {
   #pragma acc parallel 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 clause 'wait' not yet implemented, clause ignored}}
+  // expected-error at +2{{expected ')'}}
+  // expected-note at +1{{to match this '('}}
   #pragma acc parallel wait(devnum:3:queues:i, j, 1+1, 3.3
     {}
   // expected-warning at +1{{OpenACC clause 'wait' not yet implemented, clause ignored}}

>From 5c908a23013d1fb073d26c6fdb5a8bfa10f3ea88 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 5 Apr 2024 13:16:15 -0700
Subject: [PATCH 2/5] Change diagnostic as suggested by Endilll

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 238931770da3a2..9a95670eb9ae6f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12253,7 +12253,7 @@ def err_acc_construct_appertainment
     : Error<"OpenACC construct '%0' cannot be used here; it can only "
             "be used in a statement context">;
 def err_acc_clause_appertainment
-    : Error<"OpenACC '%1' clause not valid on '%0' directive">;
+    : Error<"OpenACC '%1' clause is not valid on '%0' directive">;
 def err_acc_branch_in_out_compute_construct
     : Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 "
             "OpenACC Compute Construct">;

>From ebb2f33b17ca9ebbda3a03116f051be4b2c98008 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Mon, 8 Apr 2024 07:55:07 -0700
Subject: [PATCH 3/5] Switch to ArrayRef instead of Mutable

---
 clang/include/clang/Sema/SemaOpenACC.h |  2 +-
 clang/lib/Sema/SemaOpenACC.cpp         | 12 ++++++------
 clang/lib/Sema/TreeTransform.h         |  8 +++++---
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index bd27418e4c646c..f36da661c8c1a4 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -87,7 +87,7 @@ class SemaOpenACC : public SemaBase {
   StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K,
                                    SourceLocation StartLoc,
                                    SourceLocation EndLoc,
-                                   MutableArrayRef<OpenACCClause *> Clauses,
+                                   ArrayRef<OpenACCClause *> Clauses,
                                    StmtResult AssocStmt);
 
   /// Called after the directive has been completely parsed, including the
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 9a101581128bcd..065209967a635d 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -51,15 +51,13 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
 
 /// Destruct and deallocate any clauses that aren't going to be used because
 /// they don't have a Construct to attach to.
-void DestroyUnusedClauses(ASTContext &Ctx,
-                          MutableArrayRef<OpenACCClause *> Clauses) {
+void DestroyUnusedClauses(ASTContext &Ctx, ArrayRef<OpenACCClause *> Clauses) {
   auto *Itr = Clauses.begin();
   auto *End = Clauses.end();
 
   for (; Itr != End; ++Itr) {
     (*Itr)->~OpenACCClause();
     Ctx.Deallocate(*Itr);
-    *Itr = nullptr;
   }
 }
 } // namespace
@@ -114,9 +112,11 @@ bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K,
   return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
 }
 
-StmtResult SemaOpenACC::ActOnEndStmtDirective(
-    OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation EndLoc,
-    MutableArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
+StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
+                                              SourceLocation StartLoc,
+                                              SourceLocation EndLoc,
+                                              ArrayRef<OpenACCClause *> Clauses,
+                                              StmtResult AssocStmt) {
   switch (K) {
   default:
     DestroyUnusedClauses(getASTContext(), Clauses);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 49f517745c079f..e10d9dd2e65174 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4002,9 +4002,11 @@ class TreeTransform {
     return getSema().CreateRecoveryExpr(BeginLoc, EndLoc, SubExprs, Type);
   }
 
-  StmtResult RebuildOpenACCComputeConstruct(
-      OpenACCDirectiveKind K, SourceLocation BeginLoc, SourceLocation EndLoc,
-      MutableArrayRef<OpenACCClause *> Clauses, StmtResult StrBlock) {
+  StmtResult RebuildOpenACCComputeConstruct(OpenACCDirectiveKind K,
+                                            SourceLocation BeginLoc,
+                                            SourceLocation EndLoc,
+                                            ArrayRef<OpenACCClause *> Clauses,
+                                            StmtResult StrBlock) {
     return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, EndLoc,
                                                      Clauses, StrBlock);
   }

>From a6e4ebaed14da1386e8de487347a22ebbeec4a6c Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Mon, 8 Apr 2024 07:59:12 -0700
Subject: [PATCH 4/5] Fix clang-format issue

---
 clang/include/clang/Sema/SemaOpenACC.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index f36da661c8c1a4..45929e4a9db3f1 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -21,7 +21,7 @@
 #include "clang/Sema/SemaBase.h"
 
 namespace clang {
-  class OpenACCClause;
+class OpenACCClause;
 
 class SemaOpenACC : public SemaBase {
 public:

>From 9ad5585e8fbd73501f3c771b70d79b09003cd86c Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Mon, 8 Apr 2024 08:18:09 -0700
Subject: [PATCH 5/5] Remove 'DestroyUnusedClauses' and implementation of
 transform OpenACCClauseList, to be implemeented next patch

---
 clang/lib/Sema/SemaOpenACC.cpp | 14 -------------
 clang/lib/Sema/TreeTransform.h | 38 +++-------------------------------
 2 files changed, 3 insertions(+), 49 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 065209967a635d..f520b9bfe81193 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -48,18 +48,6 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
   }
   llvm_unreachable("Invalid clause kind");
 }
-
-/// Destruct and deallocate any clauses that aren't going to be used because
-/// they don't have a Construct to attach to.
-void DestroyUnusedClauses(ASTContext &Ctx, ArrayRef<OpenACCClause *> Clauses) {
-  auto *Itr = Clauses.begin();
-  auto *End = Clauses.end();
-
-  for (; Itr != End; ++Itr) {
-    (*Itr)->~OpenACCClause();
-    Ctx.Deallocate(*Itr);
-  }
-}
 } // namespace
 
 SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
@@ -119,10 +107,8 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
                                               StmtResult AssocStmt) {
   switch (K) {
   default:
-    DestroyUnusedClauses(getASTContext(), Clauses);
     return StmtEmpty();
   case OpenACCDirectiveKind::Invalid:
-    DestroyUnusedClauses(getASTContext(), Clauses);
     return StmtError();
   case OpenACCDirectiveKind::Parallel:
   case OpenACCDirectiveKind::Serial:
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e10d9dd2e65174..ab97b375f5161a 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4033,11 +4033,6 @@ class TreeTransform {
   llvm::SmallVector<OpenACCClause *>
   TransformOpenACCClauseList(OpenACCDirectiveKind DirKind,
                              ArrayRef<const OpenACCClause *> OldClauses);
-
-  OpenACCClause *
-  TransformOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
-                         OpenACCDirectiveKind DirKind,
-                         const OpenACCClause *OldClause);
 };
 
 template <typename Derived>
@@ -11078,40 +11073,13 @@ OMPClause *TreeTransform<Derived>::TransformOMPXBareClause(OMPXBareClause *C) {
 //===----------------------------------------------------------------------===//
 // OpenACC transformation
 //===----------------------------------------------------------------------===//
-template <typename Derived>
-OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(
-    ArrayRef<const OpenACCClause *> ExistingClauses,
-    OpenACCDirectiveKind DirKind, const OpenACCClause *OldClause) {
-
-  SemaOpenACC::OpenACCParsedClause ParsedClause(
-      DirKind, OldClause->getClauseKind(), OldClause->getBeginLoc());
-  ParsedClause.setEndLoc(OldClause->getEndLoc());
-
-  if (const auto *WithParms = dyn_cast<OpenACCClauseWithParams>(OldClause))
-    ParsedClause.setLParenLoc(WithParms->getLParenLoc());
-
-  switch (OldClause->getClauseKind()) {
-    // TODO OpenACC: Transform individual clauses, and set their info in
-    // ParsedClause.
-  default:
-    assert(false && "Unhandled OpenACC clause in TreeTransform");
-    return nullptr;
-  }
-
-  return getSema().OpenACC().ActOnClause(ExistingClauses, ParsedClause);
-}
-
 template <typename Derived>
 llvm::SmallVector<OpenACCClause *>
 TreeTransform<Derived>::TransformOpenACCClauseList(
     OpenACCDirectiveKind DirKind, ArrayRef<const OpenACCClause *> OldClauses) {
-  llvm::SmallVector<OpenACCClause *> TransformedClauses;
-  for (const auto *Clause : OldClauses) {
-    if (OpenACCClause *TransformedClause = getDerived().TransformOpenACCClause(
-            TransformedClauses, DirKind, Clause))
-      TransformedClauses.push_back(TransformedClause);
-  }
-  return TransformedClauses;
+  // TODO OpenACC: Ensure we loop through the list and transform the individual
+  // clauses.
+  return {};
 }
 
 template <typename Derived>



More information about the cfe-commits mailing list