[clang] [llvm] [OpenACC] Switch Clang to use the Flang 'appertainment' rules for cla… (PR #135372)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 11 11:16:37 PDT 2025
https://github.com/erichkeane updated https://github.com/llvm/llvm-project/pull/135372
>From 2e5a137398fc39064d26ea8ca6df192c2ed64a4d Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Thu, 10 Apr 2025 14:26:27 -0700
Subject: [PATCH 1/7] [OpenACC] Switch Clang to use the Flang 'appertainment'
rules for clauses
The Flang implemenation of OpenACC uses a .td file in the llvm/Frontend
directory to determine appertainment in 4 categories:
-Required: If this list has items in it, the directive requires at least
1 of these be present.
-AllowedExclusive: Items on this list are all allowed, but only 1 from
the list may be here (That is, they are exclusive of eachother).
-AllowedOnce: Items on this list are all allowed, but may not be
duplicated.
Allowed: Items on this list are allowed. Note th at the actual list of
'allowed' is all 4 of these lists together.
This is a draft patch to swtich Clang over to use those tables. Surgery
to get this to happen in Clang Sema was somewhat reasonable. However,
some gaps in the implementations are obvious, the existing clang
implementation disagrees with the Flang interpretation of it. SO, we're
keeping a task list here based on what gets discovered.
Changes to Clang:
- [ ] Switch 'directive-kind' enum conversions to use tablegen
- [ ] Switch 'clause-kind' enum conversions to use tablegen
- [x] Investigate 'parse' test differences to see if any new
disagreements arise.
- [x] Clang/Flang disagree as to whether 'collapse' can be multiple
times on a loop. Further research showed no prose to limit this, and
the comment on the clang implementation said "no good reason to allow",
so no standards justification.
- [x] Clang/Flang disagree whether 'num_gangs' can appear >1 on a
compute/combined construct. This ended up being an unjustified
restriction.
- [x] Clang/Flang disagree as to the list of required clauses on a 'set'
construct. My research shows that Clang mistakenly included 'if' in the
list, and that it should be just 'default_async', 'device_num', and
'device_type'.
- [x] Order of 'at least one of' diagnostic has changed. Tests were
updated.
Changes to Flang:
- [ ] Clang/Flang disgree on whether 'atomic' can take an 'if' clause.
This was added in OpenACC3.3_Next
Changes that need discussion/research:
- [ ] Clang/Flang disagree on whether 'init'/'shutdown' can have
multiple 'device_type' clauses. I believe there is no supporting prose
for this limitation.
- [ ] Clang/Flang disagree on whether 'init'/'shutdown' can have
multiple 'device_num' clauses. I believe there is no supporting prose
for this limitation.,
- [ ] Clang/Flang disagree on whether 'init'/'shutdown' can have
multiple 'if' clauses. I believe there is no supporting prose for this
limitation.
- [ ] Clang/Flang disagree on whether 'bind' can appear >1 on a
'routine'. I believe line 3096 (A bind clause may not bind to a routine
name that has a visible bind clause) makes this limitation.
- [ ] Clang/Flang disagree on whether 'gang', 'worker', 'vector', 'seq'
may appear multiple times on a 'routine'. Line 3080(Exactly one of the
gang, worker, vector, or seq clauses must appear). It is the flang
opinion that it means once-per-'device_type' (and once before each
device_type).
- [ ] Clang/Flang disagree as to whether 'tile' is permitted more than
once on a 'loop' or combined constructs (Flang prohibits >1). I see no
justification for this in the standard.
- [ ] Clang/Flang disagree whether 'loop' or combined constructs can
have 'seq', 'independent', or 'auto' with a 'device_type' clause. I see
no prose to suggest this limitation.
- [ ] Clang/Flang disagree whether 'gang', 'worker', or 'vector' may
appear on the same construct as a 'seq' on a 'loop' or 'combined'. There
is prose for this in 2022: (a gang, worker, or vector clause may not
appear if a 'seq' clause appears).
- [ ] Clang/Flang disagree on clause list that may appear with a
'auto'/'independent', or 'seq' clause. for a 'loop' or 'combined'.
Flang seems to be rejecting everything, which doesn't seem correct to
me, as I can find no supporting prose. This MIGHT be a bug/difference in
implementation?
- [ ] Clang/Flang disagree whether 'num_gangs' can appear >1 on a
'kernels' construct. Line 1173 (On a kernels construct, the num_gangs
clause must have a single argument) justifies limiting on a per-clause
basis, but doesn't do so for multiple num_gangs. ALSO: IF we decide such
a restriction means this, it needs to be applied to `kernels loop` as
well.
- [ ] Clang/Flang disagree whether 'finalize' and 'if_present' should be
allowed >1 times on a 'exit_data' construct. I see no prose to support
this?
- [ ] Clang/Flang disagree whether 'seq' and 'self' can appear on the
same serial-loop construct. I see no prose to support this?
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 -
clang/include/clang/Sema/SemaOpenACC.h | 18 +
clang/lib/Sema/CMakeLists.txt | 1 +
clang/lib/Sema/SemaOpenACC.cpp | 121 +--
clang/lib/Sema/SemaOpenACCClause.cpp | 717 +-----------------
.../Sema/SemaOpenACCClauseAppertainment.cpp | 340 +++++++++
.../AST/ast-print-openacc-set-construct.cpp | 4 +-
clang/test/ParserOpenACC/parse-clauses.c | 42 +-
clang/test/ParserOpenACC/parse-constructs.c | 10 +-
...d-construct-auto_seq_independent-clauses.c | 12 +-
.../combined-construct-collapse-clause.cpp | 4 +-
.../combined-construct-if-clause.c | 2 +-
.../combined-construct-num_gangs-clause.c | 4 -
.../compute-construct-device_type-clause.c | 4 +-
.../SemaOpenACC/compute-construct-if-clause.c | 2 +-
.../compute-construct-num_gangs-clause.c | 4 -
.../SemaOpenACC/data-construct-copy-clause.c | 4 +-
.../data-construct-copyin-clause.c | 2 +-
.../data-construct-copyout-clause.c | 2 +-
.../data-construct-create-clause.c | 2 +-
.../data-construct-default-clause.c | 6 +-
.../data-construct-delete-clause.c | 4 +-
.../data-construct-device_type-clause.c | 2 +-
.../data-construct-no_create-clause.c | 4 +-
.../data-construct-use_device-clause.c | 6 +-
clang/test/SemaOpenACC/data-construct.cpp | 28 +-
...p-construct-auto_seq_independent-clauses.c | 18 +-
.../loop-construct-collapse-clause.cpp | 11 +-
clang/test/SemaOpenACC/no-empty-pqr-list.cpp | 2 +-
clang/test/SemaOpenACC/set-construct.cpp | 15 +-
clang/test/SemaOpenACC/update-construct.cpp | 10 +-
31 files changed, 478 insertions(+), 926 deletions(-)
create mode 100644 clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 180ca39bc07e9..91dcd6e65e5d0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12929,9 +12929,6 @@ def note_acc_reduction_composite_member_loc : Note<"invalid field is here">;
def err_acc_loop_not_for_loop
: Error<"OpenACC '%0' construct can only be applied to a 'for' loop">;
def note_acc_construct_here : Note<"'%0' construct is here">;
-def err_acc_loop_spec_conflict
- : Error<"OpenACC clause '%0' on '%1' construct conflicts with previous "
- "data dependence clause">;
def err_acc_collapse_loop_count
: Error<"OpenACC 'collapse' clause loop count must be a %select{constant "
"expression|positive integer value, evaluated to %1}0">;
diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index 4c3a13a3b044f..13be254f20ade 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -28,6 +28,9 @@
#include <utility>
#include <variant>
+namespace {
+class SemaOpenACCClauseVisitor;
+}
namespace clang {
class IdentifierInfo;
class OpenACCClause;
@@ -177,6 +180,21 @@ class SemaOpenACC : public SemaBase {
void CheckLastRoutineDeclNameConflict(const NamedDecl *ND);
+ bool DiagnoseRequiredClauses(OpenACCDirectiveKind DK, SourceLocation DirLoc,
+ ArrayRef<const OpenACCClause *> Clauses);
+
+ bool DiagnoseAllowedClauses(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
+ SourceLocation ClauseLoc);
+
+public:
+ // Needed from the visitor, so should be public.
+ bool DiagnoseAllowedOnceClauses(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
+ SourceLocation ClauseLoc,
+ ArrayRef<const OpenACCClause *> Clauses);
+ bool DiagnoseExclusiveClauses(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
+ SourceLocation ClauseLoc,
+ ArrayRef<const OpenACCClause *> Clauses);
+
public:
ComputeConstructInfo &getActiveComputeConstructInfo() {
return ActiveComputeConstructInfo;
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index cc7921fc32254..d0b0508eb263a 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -75,6 +75,7 @@ add_clang_library(clangSema
SemaOpenACC.cpp
SemaOpenACCAtomic.cpp
SemaOpenACCClause.cpp
+ SemaOpenACCClauseAppertainment.cpp
SemaOpenCL.cpp
SemaOpenMP.cpp
SemaOverload.cpp
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index c80f5f848f60b..6064485a108d1 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -1426,30 +1426,6 @@ void SemaOpenACC::ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body) {
}
namespace {
-// Get a list of clause Kinds for diagnosing a list, joined by a commas and an
-// 'or'.
-std::string GetListOfClauses(llvm::ArrayRef<OpenACCClauseKind> Clauses) {
- assert(!Clauses.empty() && "empty clause list not supported");
-
- std::string Output;
- llvm::raw_string_ostream OS{Output};
-
- if (Clauses.size() == 1) {
- OS << '\'' << Clauses[0] << '\'';
- return Output;
- }
-
- llvm::ArrayRef<OpenACCClauseKind> AllButLast{Clauses.begin(),
- Clauses.end() - 1};
-
- llvm::interleave(
- AllButLast, [&](OpenACCClauseKind K) { OS << '\'' << K << '\''; },
- [&] { OS << ", "; });
-
- OS << " or \'" << Clauses.back() << '\'';
- return Output;
-}
-
// Helper that should mirror ActOnRoutineName to get the FunctionDecl out for
// magic-static checking.
FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {
@@ -1682,86 +1658,8 @@ bool SemaOpenACC::ActOnStartStmtDirective(
<< OpenACCClauseKind::Tile;
}
- // OpenACC3.3 2.6.5: At least one copy, copyin, copyout, create, no_create,
- // present, deviceptr, attach, or default clause must appear on a 'data'
- // construct.
- if (K == OpenACCDirectiveKind::Data &&
- llvm::find_if(Clauses,
- llvm::IsaPred<OpenACCCopyClause, OpenACCCopyInClause,
- OpenACCCopyOutClause, OpenACCCreateClause,
- OpenACCNoCreateClause, OpenACCPresentClause,
- OpenACCDevicePtrClause, OpenACCAttachClause,
- OpenACCDefaultClause>) == Clauses.end())
- return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
- << K
- << GetListOfClauses(
- {OpenACCClauseKind::Copy, OpenACCClauseKind::CopyIn,
- OpenACCClauseKind::CopyOut, OpenACCClauseKind::Create,
- OpenACCClauseKind::NoCreate, OpenACCClauseKind::Present,
- OpenACCClauseKind::DevicePtr, OpenACCClauseKind::Attach,
- OpenACCClauseKind::Default});
-
- // OpenACC3.3 2.6.6: At least one copyin, create, or attach clause must appear
- // on an enter data directive.
- if (K == OpenACCDirectiveKind::EnterData &&
- llvm::find_if(Clauses,
- llvm::IsaPred<OpenACCCopyInClause, OpenACCCreateClause,
- OpenACCAttachClause>) == Clauses.end())
- return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
- << K
- << GetListOfClauses({
- OpenACCClauseKind::CopyIn,
- OpenACCClauseKind::Create,
- OpenACCClauseKind::Attach,
- });
- // OpenACC3.3 2.6.6: At least one copyout, delete, or detach clause must
- // appear on an exit data directive.
- if (K == OpenACCDirectiveKind::ExitData &&
- llvm::find_if(Clauses,
- llvm::IsaPred<OpenACCCopyOutClause, OpenACCDeleteClause,
- OpenACCDetachClause>) == Clauses.end())
- return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
- << K
- << GetListOfClauses({
- OpenACCClauseKind::CopyOut,
- OpenACCClauseKind::Delete,
- OpenACCClauseKind::Detach,
- });
-
- // OpenACC3.3 2.8: At least 'one use_device' clause must appear.
- if (K == OpenACCDirectiveKind::HostData &&
- llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDeviceClause>) ==
- Clauses.end())
- return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
- << K << GetListOfClauses({OpenACCClauseKind::UseDevice});
-
- // OpenACC3.3 2.14.3: At least one default_async, device_num, or device_type
- // clause must appear.
- if (K == OpenACCDirectiveKind::Set &&
- llvm::find_if(
- Clauses,
- llvm::IsaPred<OpenACCDefaultAsyncClause, OpenACCDeviceNumClause,
- OpenACCDeviceTypeClause, OpenACCIfClause>) ==
- Clauses.end())
- return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
- << K
- << GetListOfClauses({OpenACCClauseKind::DefaultAsync,
- OpenACCClauseKind::DeviceNum,
- OpenACCClauseKind::DeviceType,
- OpenACCClauseKind::If});
-
- // OpenACC3.3 2.14.4: At least one self, host, or device clause must appear on
- // an update directive.
- if (K == OpenACCDirectiveKind::Update &&
- llvm::find_if(Clauses, llvm::IsaPred<OpenACCSelfClause, OpenACCHostClause,
- OpenACCDeviceClause>) ==
- Clauses.end())
- return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
- << K
- << GetListOfClauses({OpenACCClauseKind::Self,
- OpenACCClauseKind::Host,
- OpenACCClauseKind::Device});
-
+ if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
+ return true;
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
}
@@ -1939,19 +1837,8 @@ bool SemaOpenACC::ActOnStartDeclDirective(
SemaRef.DiscardCleanupsInEvaluationContext();
SemaRef.PopExpressionEvaluationContext();
- if (K == OpenACCDirectiveKind::Routine &&
- llvm::find_if(Clauses,
- llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
- OpenACCVectorClause, OpenACCSeqClause>) ==
- Clauses.end())
- return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
- << K
- << GetListOfClauses({
- OpenACCClauseKind::Gang,
- OpenACCClauseKind::Worker,
- OpenACCClauseKind::Vector,
- OpenACCClauseKind::Seq,
- });
+ if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
+ return true;
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
}
diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp
index ab25dcfd1a081..edf9cb36b59d1 100644
--- a/clang/lib/Sema/SemaOpenACCClause.cpp
+++ b/clang/lib/Sema/SemaOpenACCClause.cpp
@@ -20,502 +20,6 @@
using namespace clang;
namespace {
-bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
- OpenACCClauseKind ClauseKind) {
- switch (ClauseKind) {
- // FIXME: For each clause as we implement them, we can add the
- // 'legalization' list here.
- case OpenACCClauseKind::Default:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- case OpenACCDirectiveKind::Data:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::If:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::EnterData:
- case OpenACCDirectiveKind::ExitData:
- case OpenACCDirectiveKind::HostData:
- case OpenACCDirectiveKind::Init:
- case OpenACCDirectiveKind::Shutdown:
- case OpenACCDirectiveKind::Set:
- case OpenACCDirectiveKind::Update:
- case OpenACCDirectiveKind::Wait:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- // OpenACC 3.4(prerelease) PR #511 adds 'if' to atomic.
- case OpenACCDirectiveKind::Atomic:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::Self:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Update:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::NumGangs:
- case OpenACCClauseKind::NumWorkers:
- case OpenACCClauseKind::VectorLength:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::FirstPrivate:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::Private:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::NoCreate:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::Present:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::Declare:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
-
- case OpenACCClauseKind::Copy:
- case OpenACCClauseKind::PCopy:
- case OpenACCClauseKind::PresentOrCopy:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::Declare:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::CopyIn:
- case OpenACCClauseKind::PCopyIn:
- case OpenACCClauseKind::PresentOrCopyIn:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::EnterData:
- case OpenACCDirectiveKind::Declare:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::CopyOut:
- case OpenACCClauseKind::PCopyOut:
- case OpenACCClauseKind::PresentOrCopyOut:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::ExitData:
- case OpenACCDirectiveKind::Declare:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::Create:
- case OpenACCClauseKind::PCreate:
- case OpenACCClauseKind::PresentOrCreate:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::EnterData:
- case OpenACCDirectiveKind::Declare:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
-
- case OpenACCClauseKind::Attach:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::EnterData:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::DevicePtr:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::Declare:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::Async:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::EnterData:
- case OpenACCDirectiveKind::ExitData:
- case OpenACCDirectiveKind::Set:
- case OpenACCDirectiveKind::Update:
- case OpenACCDirectiveKind::Wait:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::Wait:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::EnterData:
- case OpenACCDirectiveKind::ExitData:
- case OpenACCDirectiveKind::Update:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
-
- case OpenACCClauseKind::Seq:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::Routine:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
-
- case OpenACCClauseKind::Independent:
- case OpenACCClauseKind::Auto:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
-
- case OpenACCClauseKind::Reduction:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
-
- case OpenACCClauseKind::DeviceType:
- case OpenACCClauseKind::DType:
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Parallel:
- case OpenACCDirectiveKind::Serial:
- case OpenACCDirectiveKind::Kernels:
- case OpenACCDirectiveKind::Data:
- case OpenACCDirectiveKind::Init:
- case OpenACCDirectiveKind::Shutdown:
- case OpenACCDirectiveKind::Set:
- case OpenACCDirectiveKind::Update:
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::Routine:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
-
- case OpenACCClauseKind::Collapse: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Tile: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- return true;
- default:
- return false;
- }
- }
-
- case OpenACCClauseKind::Gang: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- case OpenACCDirectiveKind::Routine:
- return true;
- default:
- return false;
- }
- case OpenACCClauseKind::Worker: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- case OpenACCDirectiveKind::Routine:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Vector: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Loop:
- case OpenACCDirectiveKind::ParallelLoop:
- case OpenACCDirectiveKind::SerialLoop:
- case OpenACCDirectiveKind::KernelsLoop:
- case OpenACCDirectiveKind::Routine:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Finalize: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::ExitData:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::IfPresent: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::HostData:
- case OpenACCDirectiveKind::Update:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Delete: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::ExitData:
- return true;
- default:
- return false;
- }
- }
-
- case OpenACCClauseKind::Detach: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::ExitData:
- return true;
- default:
- return false;
- }
- }
-
- case OpenACCClauseKind::DeviceNum: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Init:
- case OpenACCDirectiveKind::Shutdown:
- case OpenACCDirectiveKind::Set:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Link: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Declare:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::DeviceResident: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Declare:
- return true;
- default:
- return false;
- }
- }
-
- case OpenACCClauseKind::UseDevice: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::HostData:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::DefaultAsync: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Set:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Device: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Update:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Host: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Update:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::NoHost: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Routine:
- return true;
- default:
- return false;
- }
- }
- case OpenACCClauseKind::Bind: {
- switch (DirectiveKind) {
- case OpenACCDirectiveKind::Routine:
- return true;
- default:
- return false;
- }
- }
- }
-
- default:
- // Do nothing so we can go to the 'unimplemented' diagnostic instead.
- return true;
- }
- llvm_unreachable("Invalid clause kind");
-}
-
-bool checkAlreadyHasClauseOfKind(
- SemaOpenACC &S, ArrayRef<const OpenACCClause *> ExistingClauses,
- SemaOpenACC::OpenACCParsedClause &Clause) {
- const auto *Itr = llvm::find_if(ExistingClauses, [&](const OpenACCClause *C) {
- return C->getClauseKind() == Clause.getClauseKind();
- });
- if (Itr != ExistingClauses.end()) {
- S.Diag(Clause.getBeginLoc(), diag::err_acc_duplicate_clause_disallowed)
- << Clause.getDirectiveKind() << Clause.getClauseKind();
- S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- return true;
- }
- return false;
-}
bool checkValidAfterDeviceType(
SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,
const SemaOpenACC::OpenACCParsedClause &NewClause) {
@@ -627,14 +131,6 @@ bool checkValidAfterDeviceType(
return true;
}
-// A temporary function that helps implement the 'not implemented' check at the
-// top of each clause checking function. This should only be used in conjunction
-// with the one being currently implemented/only updated after the entire
-// construct has been implemented.
-bool isDirectiveKindImplemented(OpenACCDirectiveKind DK) {
- return DK != OpenACCDirectiveKind::Routine;
-}
-
// GCC looks through linkage specs, but not the other transparent declaration
// contexts for 'declare' restrictions, so this helper function helps get us
// through that.
@@ -649,39 +145,6 @@ class SemaOpenACCClauseVisitor {
SemaOpenACC &SemaRef;
ASTContext &Ctx;
ArrayRef<const OpenACCClause *> ExistingClauses;
- bool NotImplemented = false;
-
- OpenACCClause *isNotImplemented() {
- NotImplemented = true;
- return nullptr;
- }
-
- // OpenACC 3.3 2.9:
- // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
- // appears.
- // -also-
- // OpenACC3.3 2.15: (routine)
- // Exactly one of the 'gang', 'worker', 'vector' or 'seq' clauses must appear.
- bool
- DiagGangWorkerVectorSeqConflict(SemaOpenACC::OpenACCParsedClause &Clause) {
- const auto *Itr =
- Clause.getDirectiveKind() == OpenACCDirectiveKind::Routine
- ? llvm::find_if(
- ExistingClauses,
- llvm::IsaPred<OpenACCSeqClause, OpenACCGangClause,
- OpenACCWorkerClause, OpenACCVectorClause>)
- : llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
-
- if (Itr != ExistingClauses.end()) {
- SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
- << Clause.getClauseKind() << (*Itr)->getClauseKind()
- << Clause.getDirectiveKind();
- SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
-
- return true;
- }
- return false;
- }
OpenACCModifierKind
CheckModifierList(SemaOpenACC::OpenACCParsedClause &Clause,
@@ -742,7 +205,18 @@ class SemaOpenACCClauseVisitor {
: SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}
OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
+
+ if (SemaRef.DiagnoseAllowedOnceClauses(
+ Clause.getDirectiveKind(), Clause.getClauseKind(),
+ Clause.getBeginLoc(), ExistingClauses) ||
+ SemaRef.DiagnoseExclusiveClauses(Clause.getDirectiveKind(),
+ Clause.getClauseKind(),
+ Clause.getBeginLoc(), ExistingClauses))
+ return nullptr;
+
switch (Clause.getClauseKind()) {
+ case OpenACCClauseKind::Invalid:
+ return nullptr;
#define VISIT_CLAUSE(CLAUSE_NAME) \
case OpenACCClauseKind::CLAUSE_NAME: \
return Visit##CLAUSE_NAME##Clause(Clause);
@@ -753,8 +227,6 @@ class SemaOpenACCClauseVisitor {
<< Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME; \
return Visit##CLAUSE_NAME##Clause(Clause);
#include "clang/Basic/OpenACCClauses.def"
- default:
- return isNotImplemented();
}
llvm_unreachable("Invalid clause kind");
}
@@ -771,13 +243,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(
if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
return nullptr;
- // OpenACC 3.3, Section 2.5.4:
- // At most one 'default' clause may appear, and it must have a value of
- // either 'none' or 'present'.
- // Second half of the sentence is diagnosed during parsing.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
-
return OpenACCDefaultClause::Create(
Ctx, Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
Clause.getLParenLoc(), Clause.getEndLoc());
@@ -786,14 +251,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // Duplicates here are not really sensible. We could possible permit
- // multiples if they all had the same value, but there isn't really a good
- // reason to do so. Also, this simplifies the suppression of duplicates, in
- // that we know if we 'find' one after instantiation, that it is the same
- // clause, which simplifies instantiation/checking/etc.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
-
llvm::SmallVector<Expr *> NewSizeExprs;
// Make sure these are all positive constant expressions or *.
@@ -813,16 +270,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // There is no prose in the standard that says duplicates aren't allowed,
- // but this diagnostic is present in other compilers, as well as makes
- // sense. Prose DOES exist for 'data' and 'host_data', 'set', 'enter data' and
- // 'exit data' both don't, but other implmementations do this. OpenACC issue
- // 519 filed for the latter two. Prose also exists for 'update'.
- // GCC allows this on init/shutdown, presumably for good reason, so we do too.
- if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Init &&
- Clause.getDirectiveKind() != OpenACCDirectiveKind::Shutdown &&
- checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
// The parser has ensured that we have a proper condition expr, so there
// isn't really much to do here.
@@ -845,11 +292,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // There is no prose in the standard that says duplicates aren't allowed,
- // but this diagnostic is present in other compilers, as well as makes
- // sense.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
// If the 'if' clause is true, it makes the 'self' clause have no effect,
// diagnose that here. This only applies on compute/combined constructs.
@@ -871,11 +313,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // There is no prose in the standard that says duplicates aren't allowed,
- // but this diagnostic is present in other compilers, as well as makes
- // sense.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
// num_gangs requires at least 1 int expr in all forms. Diagnose here, but
// allow us to continue, an empty clause might be useful for future
@@ -966,11 +403,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // There is no prose in the standard that says duplicates aren't allowed,
- // but this diagnostic is present in other compilers, as well as makes
- // sense.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
// OpenACC 3.3 Section 2.9.2:
// An argument is allowed only when the 'num_workers' does not appear on the
@@ -1000,12 +432,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // There is no prose in the standard that says duplicates aren't allowed,
- // but this diagnostic is present in other compilers, as well as makes
- // sense.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
-
// OpenACC 3.3 Section 2.9.4:
// An argument is allowed only when the 'vector_length' does not appear on the
// 'kernels' construct.
@@ -1034,12 +460,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // There is no prose in the standard that says duplicates aren't allowed,
- // but this diagnostic is present in other compilers, as well as makes
- // sense.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
-
assert(Clause.getNumIntExprs() < 2 &&
"Invalid number of expressions for Async");
return OpenACCAsyncClause::Create(
@@ -1050,17 +470,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // Restrictions only properly implemented on certain constructs, so skip/treat
- // as unimplemented in those cases.
- if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
- return isNotImplemented();
-
- // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
- // same directive.
- if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
- checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
-
assert(Clause.getNumIntExprs() == 1 &&
"Invalid number of expressions for device_num");
return OpenACCDeviceNumClause::Create(
@@ -1070,11 +479,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultAsyncClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
- // same directive.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
-
assert(Clause.getNumIntExprs() == 1 &&
"Invalid number of expressions for default_async");
return OpenACCDefaultAsyncClause::Create(
@@ -1332,11 +736,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
- // same directive.
- if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
- checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
// Based on discussions, having more than 1 'architecture' on a 'set' is
// nonsensical, so we're going to fix the standard to reflect this. Implement
@@ -1396,18 +795,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // OpenACC 3.3 2.9:
- // Only one of the seq, independent, and auto clauses may appear.
- const auto *Itr =
- llvm::find_if(ExistingClauses,
- llvm::IsaPred<OpenACCAutoClause, OpenACCIndependentClause,
- OpenACCSeqClause>);
- if (Itr != ExistingClauses.end()) {
- SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
- << Clause.getClauseKind() << Clause.getDirectiveKind();
- SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- return nullptr;
- }
return OpenACCAutoClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getEndLoc());
@@ -1421,17 +808,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNoHostClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // OpenACC 3.3 2.9:
- // Only one of the seq, independent, and auto clauses may appear.
- const auto *Itr = llvm::find_if(
- ExistingClauses, llvm::IsaPred<OpenACCIndependentClause,
- OpenACCAutoClause, OpenACCSeqClause>);
- if (Itr != ExistingClauses.end()) {
- SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
- << Clause.getClauseKind() << Clause.getDirectiveKind();
- SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- return nullptr;
- }
return OpenACCIndependentClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getEndLoc());
@@ -1596,9 +972,6 @@ ExprResult CheckGangRoutineExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- if (DiagGangWorkerVectorSeqConflict(Clause))
- return nullptr;
-
Expr *IntExpr =
Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
if (IntExpr) {
@@ -1695,9 +1068,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- if (DiagGangWorkerVectorSeqConflict(Clause))
- return nullptr;
-
Expr *IntExpr =
Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
@@ -1804,9 +1174,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- if (DiagGangWorkerVectorSeqConflict(Clause))
- return nullptr;
-
// OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
// directive that has a gang clause and is within a compute construct that has
// a num_gangs clause with more than one explicit argument.
@@ -1944,44 +1311,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfPresentClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Routine) {
- // OpenACC 3.3 2.9:
- // Only one of the seq, independent, and auto clauses may appear.
- const auto *Itr =
- llvm::find_if(ExistingClauses,
- llvm::IsaPred<OpenACCAutoClause, OpenACCIndependentClause,
- OpenACCSeqClause>);
- if (Itr != ExistingClauses.end()) {
- SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
- << Clause.getClauseKind() << Clause.getDirectiveKind();
- SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- return nullptr;
- }
- }
-
- // OpenACC 3.3 2.9:
- // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
- // appears.
- // -also-
- // OpenACC3.3 2.15: (routine)
- // Exactly one of the 'gang', 'worker', 'vector' or 'seq' clauses must appear.
- const auto *Itr =
- Clause.getDirectiveKind() == OpenACCDirectiveKind::Routine
- ? llvm::find_if(ExistingClauses,
- llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
- OpenACCVectorClause, OpenACCSeqClause>)
- : llvm::find_if(ExistingClauses,
- llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
- OpenACCVectorClause>);
-
- if (Itr != ExistingClauses.end()) {
- SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
- << Clause.getClauseKind() << (*Itr)->getClauseKind()
- << Clause.getDirectiveKind();
- SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- return nullptr;
- }
-
return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getEndLoc());
}
@@ -2082,13 +1411,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- // Duplicates here are not really sensible. We could possible permit
- // multiples if they all had the same value, but there isn't really a good
- // reason to do so. Also, this simplifies the suppression of duplicates, in
- // that we know if we 'find' one after instantiation, that it is the same
- // clause, which simplifies instantiation/checking/etc.
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
ExprResult LoopCount = SemaRef.CheckCollapseLoopCount(Clause.getLoopCount());
@@ -2102,8 +1424,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
OpenACCClause *SemaOpenACCClauseVisitor::VisitBindClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
- if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
- return nullptr;
if (std::holds_alternative<StringLiteral *>(Clause.getBindDetails()))
return OpenACCBindClause::Create(
@@ -2181,13 +1501,16 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
return nullptr;
- // Diagnose that we don't support this clause on this directive.
- if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
- Clause.getClauseKind())) {
- Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
- << Clause.getDirectiveKind() << Clause.getClauseKind();
+ if (DiagnoseAllowedClauses(Clause.getDirectiveKind(), Clause.getClauseKind(),
+ Clause.getBeginLoc()))
return nullptr;
- }
+ //// Diagnose that we don't support this clause on this directive.
+ // if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
+ // Clause.getClauseKind())) {
+ // Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
+ // << Clause.getDirectiveKind() << Clause.getClauseKind();
+ // return nullptr;
+ // }
if (const auto *DevTypeClause = llvm::find_if(
ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
diff --git a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
new file mode 100644
index 0000000000000..89d81f1d3bd43
--- /dev/null
+++ b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
@@ -0,0 +1,340 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements conversions from the ACC.td from the backend to
+/// determine appertainment, required/etc.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DiagnosticSema.h"
+#include "clang/Sema/SemaOpenACC.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/bit.h"
+#include "llvm/Frontend/OpenACC/ACC.h.inc"
+
+namespace {
+// Implements a simple 'enum-set' which stores enum values in a single 64 bit
+// value. Flang has `EnumSet` which is pretty sizable/has a lot of dependencies,
+// so likely not worth bringing in for this use.
+class AccClauseSet {
+ // We're just using a uint64_t as our underlying rep, so if this size ever
+ // gets bigger than 64, we probably need a pair of uint64_ts.
+ static_assert(llvm::acc::Clause_enumSize <= 64);
+ uint64_t Data;
+
+ void setBit(llvm::acc::Clause C) {
+ Data |= static_cast<uint64_t>(1) << static_cast<uint64_t>(C);
+ }
+
+public:
+ constexpr AccClauseSet(
+ const std::initializer_list<llvm::acc::Clause> &Clauses)
+ : Data(0) {
+ for (llvm::acc::Clause C : Clauses)
+ setBit(C);
+ }
+
+ constexpr bool isSet(llvm::acc::Clause C) const {
+ return ((Data >> static_cast<uint64_t>(C)) & 1) != 0;
+ }
+
+ void clearBit(llvm::acc::Clause C) {
+ Data &= ~(static_cast<uint64_t>(1) << static_cast<uint64_t>(C));
+ }
+
+ constexpr bool isEmpty() const { return Data == 0; }
+
+ unsigned popcount() const { return llvm::popcount<uint64_t>(Data); }
+};
+} // namespace
+
+#define GEN_FLANG_DIRECTIVE_CLAUSE_SETS
+#include "llvm/Frontend/OpenACC/ACC.inc"
+
+using namespace clang;
+
+namespace {
+struct LLVMClauseLists {
+ AccClauseSet Allowed;
+ AccClauseSet AllowedOnce;
+ AccClauseSet AllowedExclusive;
+ AccClauseSet Required;
+};
+struct LLVMDirectiveClauseRelationships {
+ llvm::acc::Directive DirKind;
+ LLVMClauseLists Lists;
+};
+
+LLVMDirectiveClauseRelationships Relations[] =
+#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
+#include "llvm/Frontend/OpenACC/ACC.inc"
+ ;
+
+llvm::acc::Directive
+getLLVMDirectiveFromClangDirective(OpenACCDirectiveKind DK) {
+ // FIXME: There isn't any obvious way to do this automatically, but perhaps we
+ // could figure out one?
+ switch (DK) {
+ case OpenACCDirectiveKind::Parallel:
+ return llvm::acc::Directive::ACCD_parallel;
+ case OpenACCDirectiveKind::Serial:
+ return llvm::acc::Directive::ACCD_serial;
+ case OpenACCDirectiveKind::Kernels:
+ return llvm::acc::Directive::ACCD_kernels;
+ case OpenACCDirectiveKind::Data:
+ return llvm::acc::Directive::ACCD_data;
+ case OpenACCDirectiveKind::EnterData:
+ return llvm::acc::Directive::ACCD_enter_data;
+ case OpenACCDirectiveKind::ExitData:
+ return llvm::acc::Directive::ACCD_exit_data;
+ case OpenACCDirectiveKind::HostData:
+ return llvm::acc::Directive::ACCD_host_data;
+ case OpenACCDirectiveKind::Loop:
+ return llvm::acc::Directive::ACCD_loop;
+ case OpenACCDirectiveKind::Cache:
+ return llvm::acc::Directive::ACCD_cache;
+ case OpenACCDirectiveKind::ParallelLoop:
+ return llvm::acc::Directive::ACCD_parallel_loop;
+ case OpenACCDirectiveKind::SerialLoop:
+ return llvm::acc::Directive::ACCD_serial_loop;
+ case OpenACCDirectiveKind::KernelsLoop:
+ return llvm::acc::Directive::ACCD_kernels_loop;
+ case OpenACCDirectiveKind::Atomic:
+ return llvm::acc::Directive::ACCD_atomic;
+ case OpenACCDirectiveKind::Declare:
+ return llvm::acc::Directive::ACCD_declare;
+ case OpenACCDirectiveKind::Init:
+ return llvm::acc::Directive::ACCD_init;
+ case OpenACCDirectiveKind::Shutdown:
+ return llvm::acc::Directive::ACCD_shutdown;
+ case OpenACCDirectiveKind::Set:
+ return llvm::acc::Directive::ACCD_set;
+ case OpenACCDirectiveKind::Update:
+ return llvm::acc::Directive::ACCD_update;
+ case OpenACCDirectiveKind::Wait:
+ return llvm::acc::Directive::ACCD_wait;
+ case OpenACCDirectiveKind::Routine:
+ return llvm::acc::Directive::ACCD_routine;
+ case OpenACCDirectiveKind::Invalid:
+ llvm_unreachable("Shouldn't get here with an invalid directive");
+ }
+
+ llvm_unreachable("unhandled directive kind");
+}
+
+// FIXME: There isn't any obvious way to do this automatically, but perhaps we
+// could figure out one?
+std::pair<OpenACCClauseKind, llvm::acc::Clause> ClauseEquivs[]{
+ {OpenACCClauseKind::Finalize, llvm::acc::Clause::ACCC_finalize},
+ {OpenACCClauseKind::IfPresent, llvm::acc::Clause::ACCC_if_present},
+ {OpenACCClauseKind::Seq, llvm::acc::Clause::ACCC_seq},
+ {OpenACCClauseKind::Independent, llvm::acc::Clause::ACCC_independent},
+ {OpenACCClauseKind::Auto, llvm::acc::Clause::ACCC_auto},
+ {OpenACCClauseKind::Worker, llvm::acc::Clause::ACCC_worker},
+ {OpenACCClauseKind::Vector, llvm::acc::Clause::ACCC_vector},
+ {OpenACCClauseKind::NoHost, llvm::acc::Clause::ACCC_nohost},
+ {OpenACCClauseKind::Default, llvm::acc::Clause::ACCC_default},
+ {OpenACCClauseKind::If, llvm::acc::Clause::ACCC_if},
+ {OpenACCClauseKind::Self, llvm::acc::Clause::ACCC_self},
+ {OpenACCClauseKind::Copy, llvm::acc::Clause::ACCC_copy},
+ {OpenACCClauseKind::PCopy, llvm::acc::Clause::ACCC_copy},
+ {OpenACCClauseKind::PresentOrCopy, llvm::acc::Clause::ACCC_copy},
+ {OpenACCClauseKind::UseDevice, llvm::acc::Clause::ACCC_use_device},
+ {OpenACCClauseKind::Attach, llvm::acc::Clause::ACCC_attach},
+ {OpenACCClauseKind::Delete, llvm::acc::Clause::ACCC_delete},
+ {OpenACCClauseKind::Detach, llvm::acc::Clause::ACCC_detach},
+ {OpenACCClauseKind::Device, llvm::acc::Clause::ACCC_device},
+ {OpenACCClauseKind::DevicePtr, llvm::acc::Clause::ACCC_deviceptr},
+ {OpenACCClauseKind::DeviceResident,
+ llvm::acc::Clause::ACCC_device_resident},
+ {OpenACCClauseKind::FirstPrivate, llvm::acc::Clause::ACCC_firstprivate},
+ {OpenACCClauseKind::Host, llvm::acc::Clause::ACCC_host},
+ {OpenACCClauseKind::Link, llvm::acc::Clause::ACCC_link},
+ {OpenACCClauseKind::NoCreate, llvm::acc::Clause::ACCC_no_create},
+ {OpenACCClauseKind::Present, llvm::acc::Clause::ACCC_present},
+ {OpenACCClauseKind::Private, llvm::acc::Clause::ACCC_private},
+ {OpenACCClauseKind::CopyOut, llvm::acc::Clause::ACCC_copyout},
+ {OpenACCClauseKind::PCopyOut, llvm::acc::Clause::ACCC_copyout},
+ {OpenACCClauseKind::PresentOrCopyOut, llvm::acc::Clause::ACCC_copyout},
+ {OpenACCClauseKind::CopyIn, llvm::acc::Clause::ACCC_copyin},
+ {OpenACCClauseKind::PCopyIn, llvm::acc::Clause::ACCC_copyin},
+ {OpenACCClauseKind::PresentOrCopyIn, llvm::acc::Clause::ACCC_copyin},
+ {OpenACCClauseKind::Create, llvm::acc::Clause::ACCC_create},
+ {OpenACCClauseKind::PCreate, llvm::acc::Clause::ACCC_create},
+ {OpenACCClauseKind::PresentOrCreate, llvm::acc::Clause::ACCC_create},
+ {OpenACCClauseKind::Reduction, llvm::acc::Clause::ACCC_reduction},
+ {OpenACCClauseKind::Collapse, llvm::acc::Clause::ACCC_collapse},
+ {OpenACCClauseKind::Bind, llvm::acc::Clause::ACCC_bind},
+ {OpenACCClauseKind::VectorLength, llvm::acc::Clause::ACCC_vector_length},
+ {OpenACCClauseKind::NumGangs, llvm::acc::Clause::ACCC_num_gangs},
+ {OpenACCClauseKind::NumWorkers, llvm::acc::Clause::ACCC_num_workers},
+ {OpenACCClauseKind::DeviceNum, llvm::acc::Clause::ACCC_device_num},
+ {OpenACCClauseKind::DefaultAsync, llvm::acc::Clause::ACCC_default_async},
+ {OpenACCClauseKind::DeviceType, llvm::acc::Clause::ACCC_device_type},
+ {OpenACCClauseKind::DType, llvm::acc::Clause::ACCC_device_type},
+ {OpenACCClauseKind::Async, llvm::acc::Clause::ACCC_async},
+ {OpenACCClauseKind::Tile, llvm::acc::Clause::ACCC_tile},
+ {OpenACCClauseKind::Gang, llvm::acc::Clause::ACCC_gang},
+ {OpenACCClauseKind::Wait, llvm::acc::Clause::ACCC_wait}};
+
+llvm::acc::Clause getLLVMClauseFromClangClause(OpenACCClauseKind CK) {
+ assert(CK != OpenACCClauseKind::Invalid);
+
+ auto *Res =
+ llvm::find_if(ClauseEquivs, [=](auto Ref) { return CK == Ref.first; });
+ assert(Res && "Unhandled clause kind");
+
+ return Res->second;
+}
+
+OpenACCClauseKind getClangClauseFromLLVMClause(llvm::acc::Clause CK) {
+
+ auto *Res =
+ llvm::find_if(ClauseEquivs, [=](auto Ref) { return CK == Ref.second; });
+ assert(Res && "Unhandled clause kind");
+
+ return Res->first;
+}
+
+const LLVMClauseLists &getListsForDirective(OpenACCDirectiveKind DK) {
+
+ llvm::acc::Directive Dir = getLLVMDirectiveFromClangDirective(DK);
+ auto Res = llvm::find_if(Relations,
+ [=](const LLVMDirectiveClauseRelationships &Rel) {
+ return Rel.DirKind == Dir;
+ });
+ assert(Res != std::end(Relations) && "Unknown directive kind?");
+
+ return Res->Lists;
+}
+
+std::string getListOfClauses(AccClauseSet Set) {
+ // We could probably come up with a better way to do this smuggling, but this
+ // is good enough for now.
+ std::string Output;
+ llvm::raw_string_ostream OS{Output};
+
+ for (unsigned I = 0; I < llvm::acc::Clause_enumSize; ++I) {
+ llvm::acc::Clause CurClause = static_cast<llvm::acc::Clause>(I);
+ if (!Set.isSet(CurClause))
+ continue;
+
+ OpenACCClauseKind NewCK = getClangClauseFromLLVMClause(CurClause);
+ OS << '\'' << NewCK << '\'';
+
+ Set.clearBit(CurClause);
+
+ if (Set.isEmpty()) {
+ OS.flush();
+ return OS.str();
+ }
+
+ OS << ", ";
+
+ if (Set.popcount() == 1)
+ OS << "or ";
+ }
+ OS.flush();
+ return OS.str();
+}
+} // namespace
+
+// Diagnoses if `Clauses` list doesn't have at least one of the required
+// clauses.
+bool SemaOpenACC::DiagnoseRequiredClauses(
+ OpenACCDirectiveKind DK, SourceLocation DirectiveLoc,
+ ArrayRef<const OpenACCClause *> Clauses) {
+ if (DK == OpenACCDirectiveKind::Invalid)
+ return false;
+
+ const LLVMClauseLists &Lists = getListsForDirective(DK);
+
+ if (Lists.Required.isEmpty())
+ return false;
+
+ for (auto *C : Clauses) {
+ if (Lists.Required.isSet(getLLVMClauseFromClangClause(C->getClauseKind())))
+ return false;
+ }
+
+ return Diag(DirectiveLoc, diag::err_acc_construct_one_clause_of)
+ << DK << getListOfClauses(Lists.Required);
+ return true;
+}
+
+// Diagnoses a 'CK' on a 'DK' present more than once in a clause-list when it
+// isn't allowed.
+bool SemaOpenACC::DiagnoseAllowedOnceClauses(
+ OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation ClauseLoc,
+ ArrayRef<const OpenACCClause *> Clauses) {
+ if (DK == OpenACCDirectiveKind::Invalid || CK == OpenACCClauseKind::Invalid)
+ return false;
+
+ const LLVMClauseLists &Lists = getListsForDirective(DK);
+ llvm::acc::Clause LLVMClause = getLLVMClauseFromClangClause(CK);
+
+ if (!Lists.AllowedOnce.isSet(LLVMClause))
+ return false;
+
+ auto Res = llvm::find_if(Clauses, [=](const OpenACCClause *C) {
+ return C->getClauseKind() == CK;
+ });
+
+ if (Res == Clauses.end())
+ return false;
+
+ Diag(ClauseLoc, diag::err_acc_duplicate_clause_disallowed) << DK << CK;
+ Diag((*Res)->getBeginLoc(), diag::note_acc_previous_clause_here);
+ return true;
+}
+
+// Diagnoses a 'CK' on a 'DK' being added that isn't allowed to, because another
+// clause in 'Clauses' already exists.
+bool SemaOpenACC::DiagnoseExclusiveClauses(
+ OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation ClauseLoc,
+ ArrayRef<const OpenACCClause *> Clauses) {
+ if (DK == OpenACCDirectiveKind::Invalid || CK == OpenACCClauseKind::Invalid)
+ return false;
+
+ llvm::acc::Clause LLVMClause = getLLVMClauseFromClangClause(CK);
+ const LLVMClauseLists &Lists = getListsForDirective(DK);
+
+ // If this isn't on the list, this is fine.
+ if (!Lists.AllowedExclusive.isSet(LLVMClause))
+ return false;
+
+ for (const OpenACCClause *C : Clauses) {
+ llvm::acc::Clause ExistingLLVMClause = getLLVMClauseFromClangClause(CK);
+ if (Lists.AllowedExclusive.isSet(ExistingLLVMClause)) {
+ Diag(ClauseLoc, diag::err_acc_clause_cannot_combine)
+ << CK << C->getClauseKind() << DK;
+ Diag(C->getBeginLoc(), diag::note_acc_previous_clause_here);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Diagnoses if 'CK' is not allowed on a directive of 'DK'.
+bool SemaOpenACC::DiagnoseAllowedClauses(OpenACCDirectiveKind DK,
+ OpenACCClauseKind CK,
+ SourceLocation ClauseLoc) {
+ if (DK == OpenACCDirectiveKind::Invalid || CK == OpenACCClauseKind::Invalid)
+ return false;
+ const LLVMClauseLists &Lists = getListsForDirective(DK);
+ llvm::acc::Clause Clause = getLLVMClauseFromClangClause(CK);
+
+ if (!Lists.Allowed.isSet(Clause) && !Lists.AllowedOnce.isSet(Clause) &&
+ !Lists.AllowedExclusive.isSet(Clause) && !Lists.Required.isSet(Clause))
+ return Diag(ClauseLoc, diag::err_acc_clause_appertainment) << DK << CK;
+
+ return false;
+}
diff --git a/clang/test/AST/ast-print-openacc-set-construct.cpp b/clang/test/AST/ast-print-openacc-set-construct.cpp
index 869a3feb2dd93..1ad6adb17e360 100644
--- a/clang/test/AST/ast-print-openacc-set-construct.cpp
+++ b/clang/test/AST/ast-print-openacc-set-construct.cpp
@@ -15,8 +15,8 @@ void uses() {
#pragma acc set if (Int == 5) device_type(multicore) device_num(Int)
// CHECK: #pragma acc set default_async(Int)
#pragma acc set default_async(Int)
-// CHECK: #pragma acc set if(Int == 5)
-#pragma acc set if (Int == 5)
+// CHECK: #pragma acc set if(Int == 5) device_type(multicore)
+#pragma acc set if (Int == 5) device_type(multicore)
// CHECK: #pragma acc set device_type(radeon)
#pragma acc set device_type(radeon)
// CHECK: #pragma acc set device_num(Int)
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index ef0bccf390297..716d9cffab3f6 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -4,21 +4,21 @@
void func() {
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data finalize
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data finalize finalize
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{invalid OpenACC clause 'invalid'}}
#pragma acc exit data finalize invalid
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{invalid OpenACC clause 'invalid'}}
#pragma acc exit data finalize invalid invalid finalize
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data wait finalize
// expected-error at +1{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
@@ -27,41 +27,41 @@ void func() {
// expected-error at +1{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
#pragma acc host_data if_present, if_present
- // expected-error at +4{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +4{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +3{{previous clause is here}}
- // expected-error at +2{{OpenACC clause 'auto' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop seq independent auto
for(int i = 0; i < 5;++i) {}
- // expected-error at +4{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +4{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +3{{previous clause is here}}
- // expected-error at +2{{OpenACC clause 'auto' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop seq, independent auto
for(int i = 0; i < 5;++i) {}
- // expected-error at +4{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +4{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +3{{previous clause is here}}
- // expected-error at +2{{OpenACC clause 'auto' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop seq independent, auto
for(int i = 0; i < 5;++i) {}
- // expected-error at +3{{OpenACC clause 'independent' on 'kernels loop' construct conflicts with previous data dependence clause}}
- // expected-error at +2{{OpenACC clause 'auto' on 'kernels loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +3{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'kernels loop' construct}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'kernels loop' construct}}
// expected-note at +1 2{{previous clause is here}}
#pragma acc kernels loop seq independent auto
for(int i = 0; i < 5;++i) {}
- // expected-error at +3{{OpenACC clause 'independent' on 'serial loop' construct conflicts with previous data dependence clause}}
- // expected-error at +2{{OpenACC clause 'auto' on 'serial loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +3{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'serial loop' construct}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'serial loop' construct}}
// expected-note at +1 2{{previous clause is here}}
#pragma acc serial loop seq, independent auto
for(int i = 0; i < 5;++i) {}
- // expected-error at +3{{OpenACC clause 'independent' on 'parallel loop' construct conflicts with previous data dependence clause}}
- // expected-error at +2{{OpenACC clause 'auto' on 'parallel loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +3{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'parallel loop' construct}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'parallel loop' construct}}
// expected-note at +1 2{{previous clause is here}}
#pragma acc parallel loop seq independent, auto
for(int i = 0; i < 5;++i) {}
@@ -860,20 +860,20 @@ void IntExprParsing() {
#pragma acc init device_num(returns_int())
// expected-error at +2{{expected '('}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set default_async
// expected-error at +2{{expected expression}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set default_async()
// expected-error at +2{{use of undeclared identifier 'invalid'}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set default_async(invalid)
// expected-error at +3{{expected ')'}}
// expected-note at +2{{to match this '('}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set default_async(5, 4)
#pragma acc set default_async(5)
diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c
index 71e47abd3a825..ea787ca5329aa 100644
--- a/clang/test/ParserOpenACC/parse-constructs.c
+++ b/clang/test/ParserOpenACC/parse-constructs.c
@@ -54,15 +54,15 @@ void func() {
// expected-error at +1{{invalid OpenACC clause 'clause'}}
#pragma acc kernels clause list
for(;;){}
- // expected-error at +2{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +2{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
// expected-error at +1{{invalid OpenACC clause 'clause'}}
#pragma acc data clause list
for(;;){}
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{invalid OpenACC clause 'clause'}}
#pragma acc enter data clause list
for(;;){}
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{invalid OpenACC clause 'clause'}}
#pragma acc exit data clause list
for(;;){}
@@ -141,10 +141,10 @@ void func() {
#pragma acc shutdown clause list
for(;;){}
// expected-error at +2{{invalid OpenACC clause 'clause'}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set clause list
for(;;){}
- // expected-error at +2{{OpenACC 'update' construct must have at least one 'self', 'host' or 'device' clause}}
+ // expected-error at +2{{OpenACC 'update' construct must have at least one 'device', 'host', or 'self' clause}}
// expected-error at +1{{invalid OpenACC clause 'clause'}}
#pragma acc update clause list
for(;;){}
diff --git a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c
index dbba86a1ffc61..5c64c621b0e7e 100644
--- a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c
+++ b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c
@@ -8,27 +8,27 @@ void uses() {
#pragma acc parallel loop independent
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'seq' on 'parallel loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'seq' may not appear on the same construct as a 'auto' clause on a 'parallel loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc parallel loop auto seq
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'independent' on 'parallel loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'independent' may not appear on the same construct as a 'auto' clause on a 'parallel loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc parallel loop auto independent
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'auto' on 'parallel loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'parallel loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc parallel loop seq auto
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'independent' on 'parallel loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'parallel loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc parallel loop seq independent
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'auto' on 'parallel loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'independent' clause on a 'parallel loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc parallel loop independent auto
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'seq' on 'parallel loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'seq' may not appear on the same construct as a 'independent' clause on a 'parallel loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc parallel loop independent seq
for(unsigned i = 0; i < 5; ++i);
diff --git a/clang/test/SemaOpenACC/combined-construct-collapse-clause.cpp b/clang/test/SemaOpenACC/combined-construct-collapse-clause.cpp
index f2be6622007c3..3f8fb4203d0e5 100644
--- a/clang/test/SemaOpenACC/combined-construct-collapse-clause.cpp
+++ b/clang/test/SemaOpenACC/combined-construct-collapse-clause.cpp
@@ -214,7 +214,7 @@ void no_other_directives() {
#pragma acc serial loop collapse(2)
for(unsigned i = 0; i < 5; ++i) {
for(unsigned j = 0; j < 5; ++j) {
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data
;
}
@@ -222,7 +222,7 @@ void no_other_directives() {
// expected-note at +1{{active 'collapse' clause defined here}}
#pragma acc kernels loop collapse(2)
for(unsigned i = 0; i < 5; ++i) {
- // expected-error at +2{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +2{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
// expected-error at +1{{OpenACC 'data' construct cannot appear in intervening code of a 'kernels loop' with a 'collapse' clause}}
#pragma acc data
for(unsigned j = 0; j < 5; ++j) {
diff --git a/clang/test/SemaOpenACC/combined-construct-if-clause.c b/clang/test/SemaOpenACC/combined-construct-if-clause.c
index 5580fdfe22b7b..d5e42d6105963 100644
--- a/clang/test/SemaOpenACC/combined-construct-if-clause.c
+++ b/clang/test/SemaOpenACC/combined-construct-if-clause.c
@@ -43,7 +43,7 @@ void BoolExpr(int *I, float *F) {
#pragma acc kernels loop if (*I < *F)
for (unsigned i = 0; i < 5; ++i);
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data if (*I < *F)
for (unsigned i = 0; i < 5; ++i);
#pragma acc parallel loop if (*I < *F)
diff --git a/clang/test/SemaOpenACC/combined-construct-num_gangs-clause.c b/clang/test/SemaOpenACC/combined-construct-num_gangs-clause.c
index bd035bd4a51a2..d5f216748cfc1 100644
--- a/clang/test/SemaOpenACC/combined-construct-num_gangs-clause.c
+++ b/clang/test/SemaOpenACC/combined-construct-num_gangs-clause.c
@@ -25,13 +25,9 @@ void Test() {
#pragma acc parallel loop num_gangs()
for(int i = 5; i < 10;++i);
- // expected-error at +2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'kernels loop' directive}}
- // expected-note at +1{{previous clause is here}}
#pragma acc kernels loop num_gangs(1) num_gangs(2)
for(int i = 5; i < 10;++i);
- // expected-error at +2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'parallel loop' directive}}
- // expected-note at +1{{previous clause is here}}
#pragma acc parallel loop num_gangs(1) num_gangs(2)
for(int i = 5; i < 10;++i);
diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c
index 16caa7205721d..2ff6369383714 100644
--- a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c
+++ b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c
@@ -34,10 +34,10 @@ void uses() {
#pragma acc kernels dtype(MACRO)
while(1);
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'device_type' clause is not valid on 'enter data' directive}}
#pragma acc enter data device_type(I)
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'dtype' clause is not valid on 'enter data' directive}}
#pragma acc enter data dtype(I)
diff --git a/clang/test/SemaOpenACC/compute-construct-if-clause.c b/clang/test/SemaOpenACC/compute-construct-if-clause.c
index c0ea88f06284d..0064303e1e217 100644
--- a/clang/test/SemaOpenACC/compute-construct-if-clause.c
+++ b/clang/test/SemaOpenACC/compute-construct-if-clause.c
@@ -43,7 +43,7 @@ void BoolExpr(int *I, float *F) {
#pragma acc kernels if (*I < *F)
while(0);
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data if (*I < *F)
while(0);
#pragma acc parallel loop if (*I < *F)
diff --git a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c
index 40b3b652d21da..53adb2c46216e 100644
--- a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c
+++ b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c
@@ -12,13 +12,9 @@ void Test() {
#pragma acc parallel num_gangs(1)
while(1);
- // expected-error at +2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'kernels' directive}}
- // expected-note at +1{{previous clause is here}}
#pragma acc kernels num_gangs(1) num_gangs(2)
while(1);
- // expected-error at +2{{OpenACC 'num_gangs' clause cannot appear more than once on a 'parallel' directive}}
- // expected-note at +1{{previous clause is here}}
#pragma acc parallel num_gangs(1) num_gangs(2)
while(1);
diff --git a/clang/test/SemaOpenACC/data-construct-copy-clause.c b/clang/test/SemaOpenACC/data-construct-copy-clause.c
index 0b2b0534073ed..b19f3f465caaf 100644
--- a/clang/test/SemaOpenACC/data-construct-copy-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-copy-clause.c
@@ -56,10 +56,10 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo
#pragma acc data copy((float)ArrayParam[2])
;
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'copy' clause is not valid on 'enter data' directive}}
#pragma acc enter data copy(LocalInt)
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{OpenACC 'pcopy' clause is not valid on 'exit data' directive}}
#pragma acc exit data pcopy(LocalInt)
// expected-error at +2{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
diff --git a/clang/test/SemaOpenACC/data-construct-copyin-clause.c b/clang/test/SemaOpenACC/data-construct-copyin-clause.c
index edc3f0a2e91fe..9b51a28d51a3d 100644
--- a/clang/test/SemaOpenACC/data-construct-copyin-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-copyin-clause.c
@@ -63,7 +63,7 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo
#pragma acc data copyin(invalid:(float)ArrayParam[2])
;
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{OpenACC 'copyin' clause is not valid on 'exit data' directive}}
#pragma acc exit data copyin(LocalInt)
// expected-error at +2{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
diff --git a/clang/test/SemaOpenACC/data-construct-copyout-clause.c b/clang/test/SemaOpenACC/data-construct-copyout-clause.c
index 8d137e093db0e..0c2264c56fcb8 100644
--- a/clang/test/SemaOpenACC/data-construct-copyout-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-copyout-clause.c
@@ -63,7 +63,7 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo
#pragma acc data copyout(invalid:(float)ArrayParam[2])
;
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'copyout' clause is not valid on 'enter data' directive}}
#pragma acc enter data copyout(LocalInt)
// expected-error at +2{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
diff --git a/clang/test/SemaOpenACC/data-construct-create-clause.c b/clang/test/SemaOpenACC/data-construct-create-clause.c
index e49d53b17ee82..560c6b65cc502 100644
--- a/clang/test/SemaOpenACC/data-construct-create-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-create-clause.c
@@ -63,7 +63,7 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo
#pragma acc data create(invalid:(float)ArrayParam[2])
;
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{OpenACC 'create' clause is not valid on 'exit data' directive}}
#pragma acc exit data create(LocalInt)
// expected-error at +2{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
diff --git a/clang/test/SemaOpenACC/data-construct-default-clause.c b/clang/test/SemaOpenACC/data-construct-default-clause.c
index 150d3ec22dcda..9e8ee529e9b8a 100644
--- a/clang/test/SemaOpenACC/data-construct-default-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-default-clause.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 %s -fopenacc -verify
void use() {
- // expected-error at +2{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +2{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
// expected-error at +1{{invalid value for 'default' clause; expected 'present' or 'none'}}
#pragma acc data default(garbage)
;
@@ -13,11 +13,11 @@ void use() {
// expected-note at +1{{previous clause is here}}
#pragma acc data default(none) default(present)
;
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'default' clause is not valid on 'enter data' directive}}
#pragma acc enter data default(present)
;
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{OpenACC 'default' clause is not valid on 'exit data' directive}}
#pragma acc exit data default(none)
;
diff --git a/clang/test/SemaOpenACC/data-construct-delete-clause.c b/clang/test/SemaOpenACC/data-construct-delete-clause.c
index 05093dbc4e01b..d2727de8dba63 100644
--- a/clang/test/SemaOpenACC/data-construct-delete-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-delete-clause.c
@@ -37,11 +37,11 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo
// expected-error at +1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc exit data delete((float)ArrayParam[2])
- // expected-error at +2{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +2{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
// expected-error at +1{{OpenACC 'delete' clause is not valid on 'data' directive}}
#pragma acc data delete(LocalInt)
;
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'delete' clause is not valid on 'enter data' directive}}
#pragma acc enter data delete(LocalInt)
// expected-error at +2{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
diff --git a/clang/test/SemaOpenACC/data-construct-device_type-clause.c b/clang/test/SemaOpenACC/data-construct-device_type-clause.c
index e450e320fa53c..a8234224540ba 100644
--- a/clang/test/SemaOpenACC/data-construct-device_type-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-device_type-clause.c
@@ -47,7 +47,7 @@ void uses() {
// expected-note at +1{{previous clause is here}}
#pragma acc data default(none) device_type(radeon) attach(Var)
;
- // expected-error at +3{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +3{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
// expected-error at +2{{OpenACC clause 'default' may not follow a 'device_type' clause in a 'data' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc data device_type(radeon) default(none)
diff --git a/clang/test/SemaOpenACC/data-construct-no_create-clause.c b/clang/test/SemaOpenACC/data-construct-no_create-clause.c
index 0eb459eb0009a..1de39955ba8ec 100644
--- a/clang/test/SemaOpenACC/data-construct-no_create-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-no_create-clause.c
@@ -48,10 +48,10 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo
#pragma acc data no_create((float)ArrayParam[2])
;
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{OpenACC 'no_create' clause is not valid on 'exit data' directive}}
#pragma acc exit data no_create(LocalInt)
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'no_create' clause is not valid on 'enter data' directive}}
#pragma acc enter data no_create(LocalInt)
// expected-error at +2{{OpenACC 'host_data' construct must have at least one 'use_device' clause}}
diff --git a/clang/test/SemaOpenACC/data-construct-use_device-clause.c b/clang/test/SemaOpenACC/data-construct-use_device-clause.c
index c2e7fd17f8c8d..9239757b8e85d 100644
--- a/clang/test/SemaOpenACC/data-construct-use_device-clause.c
+++ b/clang/test/SemaOpenACC/data-construct-use_device-clause.c
@@ -52,14 +52,14 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo
#pragma acc host_data use_device((float)ArrayParam[2])
;
- // expected-error at +2{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +2{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
// expected-error at +1{{OpenACC 'use_device' clause is not valid on 'data' directive}}
#pragma acc data use_device(LocalInt)
;
- // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +2{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
// expected-error at +1{{OpenACC 'use_device' clause is not valid on 'enter data' directive}}
#pragma acc enter data use_device(LocalInt)
- // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +2{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
// expected-error at +1{{OpenACC 'use_device' clause is not valid on 'exit data' directive}}
#pragma acc exit data use_device(LocalInt)
}
diff --git a/clang/test/SemaOpenACC/data-construct.cpp b/clang/test/SemaOpenACC/data-construct.cpp
index e1d0c04d7fdee..ffb037d439c8e 100644
--- a/clang/test/SemaOpenACC/data-construct.cpp
+++ b/clang/test/SemaOpenACC/data-construct.cpp
@@ -43,22 +43,22 @@ void AtLeastOneOf() {
#pragma acc data default(none)
;
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data if(Var)
;
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data async
;
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data wait
;
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data device_type(*)
;
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data
;
@@ -67,13 +67,13 @@ void AtLeastOneOf() {
#pragma acc enter data create(Var)
#pragma acc enter data attach(VarPtr)
- // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
#pragma acc enter data if(Var)
- // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
#pragma acc enter data async
- // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
#pragma acc enter data wait
- // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'copyin', 'create' or 'attach' clause}}
+ // expected-error at +1{{OpenACC 'enter data' construct must have at least one 'attach', 'copyin', or 'create' clause}}
#pragma acc enter data
// Exit Data
@@ -81,15 +81,15 @@ void AtLeastOneOf() {
#pragma acc exit data delete(Var)
#pragma acc exit data detach(VarPtr)
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data if(Var)
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data async
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data wait
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data finalize
- // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete' or 'detach' clause}}
+ // expected-error at +1{{OpenACC 'exit data' construct must have at least one 'copyout', 'delete', or 'detach' clause}}
#pragma acc exit data
// Host Data
diff --git a/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c b/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c
index 2f2bd15935856..8722e862ec61d 100644
--- a/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c
+++ b/clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c
@@ -8,40 +8,40 @@ void uses() {
#pragma acc loop independent
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'seq' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'seq' may not appear on the same construct as a 'auto' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop auto seq
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'independent' may not appear on the same construct as a 'auto' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop auto independent
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'auto' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop seq auto
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'independent' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop seq independent
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'auto' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'independent' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop independent auto
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'seq' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'seq' may not appear on the same construct as a 'independent' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop independent seq
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'seq' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'seq' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop seq seq
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'independent' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'independent' may not appear on the same construct as a 'independent' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop independent independent
for(unsigned i = 0; i < 5; ++i);
- // expected-error at +2{{OpenACC clause 'auto' on 'loop' construct conflicts with previous data dependence clause}}
+ // expected-error at +2{{OpenACC clause 'auto' may not appear on the same construct as a 'auto' clause on a 'loop' construct}}
// expected-note at +1{{previous clause is here}}
#pragma acc loop auto auto
for(unsigned i = 0; i < 5; ++i);
diff --git a/clang/test/SemaOpenACC/loop-construct-collapse-clause.cpp b/clang/test/SemaOpenACC/loop-construct-collapse-clause.cpp
index 4d45d1107d03b..4c999bfa21c11 100644
--- a/clang/test/SemaOpenACC/loop-construct-collapse-clause.cpp
+++ b/clang/test/SemaOpenACC/loop-construct-collapse-clause.cpp
@@ -14,13 +14,6 @@ void only_for_loops() {
}
-void only_one_on_loop() {
- // expected-error at +2{{OpenACC 'collapse' clause cannot appear more than once on a 'loop' directive}}
- // expected-note at +1{{previous clause is here}}
-#pragma acc loop collapse(1) collapse(1)
- for(unsigned i = 0; i < 5; ++i);
-}
-
constexpr int three() { return 3; }
constexpr int one() { return 1; }
constexpr int neg() { return -1; }
@@ -323,7 +316,7 @@ void no_other_directives() {
#pragma acc loop collapse(2)
for(unsigned i = 0; i < 5; ++i) {
for(unsigned j = 0; j < 5; ++j) {
- // expected-error at +1{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +1{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
#pragma acc data
;
}
@@ -331,7 +324,7 @@ void no_other_directives() {
// expected-note at +1{{active 'collapse' clause defined here}}
#pragma acc loop collapse(2)
for(unsigned i = 0; i < 5; ++i) {
- // expected-error at +2{{OpenACC 'data' construct must have at least one 'copy', 'copyin', 'copyout', 'create', 'no_create', 'present', 'deviceptr', 'attach' or 'default' clause}}
+ // expected-error at +2{{OpenACC 'data' construct must have at least one 'attach', 'copy', 'copyin', 'copyout', 'create', 'default', 'deviceptr', 'no_create', or 'present' clause}}
// expected-error at +1{{OpenACC 'data' construct cannot appear in intervening code of a 'loop' with a 'collapse' clause}}
#pragma acc data
for(unsigned j = 0; j < 5; ++j) {
diff --git a/clang/test/SemaOpenACC/no-empty-pqr-list.cpp b/clang/test/SemaOpenACC/no-empty-pqr-list.cpp
index fdac89646a5f8..eee9c96fe2c4d 100644
--- a/clang/test/SemaOpenACC/no-empty-pqr-list.cpp
+++ b/clang/test/SemaOpenACC/no-empty-pqr-list.cpp
@@ -213,7 +213,7 @@ void Executable(int i) {
// expected-error at +1{{expected identifier}}
#pragma acc shutdown device_type()
// expected-error at +1{{expected identifier}}
-#pragma acc set if(true) device_type()
+#pragma acc set device_num(i) device_type()
// expected-error at +1{{expected identifier}}
#pragma acc update self(i) device_type()
diff --git a/clang/test/SemaOpenACC/set-construct.cpp b/clang/test/SemaOpenACC/set-construct.cpp
index ac141d097532b..1a152b898ef4a 100644
--- a/clang/test/SemaOpenACC/set-construct.cpp
+++ b/clang/test/SemaOpenACC/set-construct.cpp
@@ -23,10 +23,10 @@ void uses() {
// expected-error at +1{{value of type 'struct NotConvertible' is not contextually convertible to 'bool'}}
#pragma acc set if (NC) device_type(radeon)
- // expected-error at +2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
// expected-error at +1{{OpenACC clause 'device_num' requires expression of integer type ('struct NotConvertible' invalid)}}
#pragma acc set device_num(NC)
- // expected-error at +4{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +4{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
// expected-error at +3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}}
// expected-note@#AMBIG_INT{{conversion to integral type 'int'}}
// expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}}
@@ -36,20 +36,21 @@ void uses() {
#pragma acc set device_num(Explicit)
// expected-error at +2{{OpenACC clause 'default_async' requires expression of integer type ('struct NotConvertible' invalid)}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set default_async(NC)
// expected-error at +4{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}}
// expected-note@#AMBIG_INT{{conversion to integral type 'int'}}
// expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set default_async(Ambiguous)
// expected-error at +2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}}
// expected-note@#EXPL_CONV{{conversion to integral type 'int'}}
#pragma acc set default_async(Explicit)
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set if (true)
// expected-error at +2{{'default_async' clause cannot appear more than once on a 'set' directive}}
@@ -68,10 +69,10 @@ void uses() {
#pragma acc set device_type(acc_device_nvidia) if(true) if (true)
// expected-error at +2{{OpenACC 'device_type' clause on a 'set' construct only permits one architecture}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set device_type(nvidia, radeon)
// expected-error at +2{{OpenACC 'device_type' clause on a 'set' construct only permits one architecture}}
- // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', or 'device_type' clause}}
#pragma acc set device_type(nonsense, nvidia, radeon)
}
diff --git a/clang/test/SemaOpenACC/update-construct.cpp b/clang/test/SemaOpenACC/update-construct.cpp
index f0372736452df..a89dc1f20158a 100644
--- a/clang/test/SemaOpenACC/update-construct.cpp
+++ b/clang/test/SemaOpenACC/update-construct.cpp
@@ -36,15 +36,15 @@ void uses() {
// These diagnose because there isn't at least 1 of 'self', 'host', or
// 'device'.
- // expected-error at +1{{OpenACC 'update' construct must have at least one 'self', 'host' or 'device' clause}}
+ // expected-error at +1{{OpenACC 'update' construct must have at least one 'device', 'host', or 'self' clause}}
#pragma acc update async
- // expected-error at +1{{OpenACC 'update' construct must have at least one 'self', 'host' or 'device' clause}}
+ // expected-error at +1{{OpenACC 'update' construct must have at least one 'device', 'host', or 'self' clause}}
#pragma acc update wait
- // expected-error at +1{{OpenACC 'update' construct must have at least one 'self', 'host' or 'device' clause}}
+ // expected-error at +1{{OpenACC 'update' construct must have at least one 'device', 'host', or 'self' clause}}
#pragma acc update device_type(host)
- // expected-error at +1{{OpenACC 'update' construct must have at least one 'self', 'host' or 'device' clause}}
+ // expected-error at +1{{OpenACC 'update' construct must have at least one 'device', 'host', or 'self' clause}}
#pragma acc update if(true)
- // expected-error at +1{{OpenACC 'update' construct must have at least one 'self', 'host' or 'device' clause}}
+ // expected-error at +1{{OpenACC 'update' construct must have at least one 'device', 'host', or 'self' clause}}
#pragma acc update if_present
// expected-error at +1{{value of type 'struct NotConvertible' is not contextually convertible to 'bool'}}
>From 2b05c62a1020d60971fda9b60223c788740f03eb Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Apr 2025 08:04:07 -0700
Subject: [PATCH 2/7] Fix bug with 'exclusive clauses'
---
clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
index 89d81f1d3bd43..710d4ee8f3ce5 100644
--- a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
+++ b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
@@ -310,7 +310,8 @@ bool SemaOpenACC::DiagnoseExclusiveClauses(
return false;
for (const OpenACCClause *C : Clauses) {
- llvm::acc::Clause ExistingLLVMClause = getLLVMClauseFromClangClause(CK);
+ llvm::acc::Clause ExistingLLVMClause =
+ getLLVMClauseFromClangClause(C->getClauseKind());
if (Lists.AllowedExclusive.isSet(ExistingLLVMClause)) {
Diag(ClauseLoc, diag::err_acc_clause_cannot_combine)
<< CK << C->getClauseKind() << DK;
>From 82cb486fac0350ce7760fcb294514f8b0fe35330 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Apr 2025 08:05:33 -0700
Subject: [PATCH 3/7] Starting effort to make tablegen specifically for clang.x
---
clang/include/clang/Basic/OpenACCKinds.h | 3 +-
.../Sema/SemaOpenACCClauseAppertainment.cpp | 185 +++---------------
.../utils/TableGen/Basic/DirectiveEmitter.cpp | 10 +
3 files changed, 40 insertions(+), 158 deletions(-)
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 652831e23a758..e9f0e657e6f7c 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -328,7 +328,8 @@ enum class OpenACCClauseKind : uint8_t {
/// constructs.
Wait,
- /// Represents an invalid clause, for the purposes of parsing.
+ /// Represents an invalid clause, for the purposes of parsing. Should be
+ /// 'last'.
Invalid,
};
diff --git a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
index 710d4ee8f3ce5..ce6ca4b8d6888 100644
--- a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
+++ b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
@@ -16,7 +16,8 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/bit.h"
-#include "llvm/Frontend/OpenACC/ACC.h.inc"
+
+using namespace clang;
namespace {
// Implements a simple 'enum-set' which stores enum values in a single 64 bit
@@ -25,26 +26,26 @@ namespace {
class AccClauseSet {
// We're just using a uint64_t as our underlying rep, so if this size ever
// gets bigger than 64, we probably need a pair of uint64_ts.
- static_assert(llvm::acc::Clause_enumSize <= 64);
+ static_assert(static_assert<unsigned>(OpenACCClauseKind::Invalid) < 64);
uint64_t Data;
- void setBit(llvm::acc::Clause C) {
+ void setBit(OpenACCClauseKind C) {
Data |= static_cast<uint64_t>(1) << static_cast<uint64_t>(C);
}
public:
constexpr AccClauseSet(
- const std::initializer_list<llvm::acc::Clause> &Clauses)
+ const std::initializer_list<OpenACCClauseKind> &Clauses)
: Data(0) {
- for (llvm::acc::Clause C : Clauses)
+ for (OpenACCClauseKind C : Clauses)
setBit(C);
}
- constexpr bool isSet(llvm::acc::Clause C) const {
+ constexpr bool isSet(OpenACCClauseKind C) const {
return ((Data >> static_cast<uint64_t>(C)) & 1) != 0;
}
- void clearBit(llvm::acc::Clause C) {
+ void clearBit(OpenACCClauseKind C) {
Data &= ~(static_cast<uint64_t>(1) << static_cast<uint64_t>(C));
}
@@ -52,14 +53,7 @@ class AccClauseSet {
unsigned popcount() const { return llvm::popcount<uint64_t>(Data); }
};
-} // namespace
-
-#define GEN_FLANG_DIRECTIVE_CLAUSE_SETS
-#include "llvm/Frontend/OpenACC/ACC.inc"
-
-using namespace clang;
-namespace {
struct LLVMClauseLists {
AccClauseSet Allowed;
AccClauseSet AllowedOnce;
@@ -71,136 +65,19 @@ struct LLVMDirectiveClauseRelationships {
LLVMClauseLists Lists;
};
-LLVMDirectiveClauseRelationships Relations[] =
-#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP
-#include "llvm/Frontend/OpenACC/ACC.inc"
- ;
-
-llvm::acc::Directive
-getLLVMDirectiveFromClangDirective(OpenACCDirectiveKind DK) {
- // FIXME: There isn't any obvious way to do this automatically, but perhaps we
- // could figure out one?
- switch (DK) {
- case OpenACCDirectiveKind::Parallel:
- return llvm::acc::Directive::ACCD_parallel;
- case OpenACCDirectiveKind::Serial:
- return llvm::acc::Directive::ACCD_serial;
- case OpenACCDirectiveKind::Kernels:
- return llvm::acc::Directive::ACCD_kernels;
- case OpenACCDirectiveKind::Data:
- return llvm::acc::Directive::ACCD_data;
- case OpenACCDirectiveKind::EnterData:
- return llvm::acc::Directive::ACCD_enter_data;
- case OpenACCDirectiveKind::ExitData:
- return llvm::acc::Directive::ACCD_exit_data;
- case OpenACCDirectiveKind::HostData:
- return llvm::acc::Directive::ACCD_host_data;
- case OpenACCDirectiveKind::Loop:
- return llvm::acc::Directive::ACCD_loop;
- case OpenACCDirectiveKind::Cache:
- return llvm::acc::Directive::ACCD_cache;
- case OpenACCDirectiveKind::ParallelLoop:
- return llvm::acc::Directive::ACCD_parallel_loop;
- case OpenACCDirectiveKind::SerialLoop:
- return llvm::acc::Directive::ACCD_serial_loop;
- case OpenACCDirectiveKind::KernelsLoop:
- return llvm::acc::Directive::ACCD_kernels_loop;
- case OpenACCDirectiveKind::Atomic:
- return llvm::acc::Directive::ACCD_atomic;
- case OpenACCDirectiveKind::Declare:
- return llvm::acc::Directive::ACCD_declare;
- case OpenACCDirectiveKind::Init:
- return llvm::acc::Directive::ACCD_init;
- case OpenACCDirectiveKind::Shutdown:
- return llvm::acc::Directive::ACCD_shutdown;
- case OpenACCDirectiveKind::Set:
- return llvm::acc::Directive::ACCD_set;
- case OpenACCDirectiveKind::Update:
- return llvm::acc::Directive::ACCD_update;
- case OpenACCDirectiveKind::Wait:
- return llvm::acc::Directive::ACCD_wait;
- case OpenACCDirectiveKind::Routine:
- return llvm::acc::Directive::ACCD_routine;
- case OpenACCDirectiveKind::Invalid:
- llvm_unreachable("Shouldn't get here with an invalid directive");
- }
-
- llvm_unreachable("unhandled directive kind");
-}
-
-// FIXME: There isn't any obvious way to do this automatically, but perhaps we
-// could figure out one?
-std::pair<OpenACCClauseKind, llvm::acc::Clause> ClauseEquivs[]{
- {OpenACCClauseKind::Finalize, llvm::acc::Clause::ACCC_finalize},
- {OpenACCClauseKind::IfPresent, llvm::acc::Clause::ACCC_if_present},
- {OpenACCClauseKind::Seq, llvm::acc::Clause::ACCC_seq},
- {OpenACCClauseKind::Independent, llvm::acc::Clause::ACCC_independent},
- {OpenACCClauseKind::Auto, llvm::acc::Clause::ACCC_auto},
- {OpenACCClauseKind::Worker, llvm::acc::Clause::ACCC_worker},
- {OpenACCClauseKind::Vector, llvm::acc::Clause::ACCC_vector},
- {OpenACCClauseKind::NoHost, llvm::acc::Clause::ACCC_nohost},
- {OpenACCClauseKind::Default, llvm::acc::Clause::ACCC_default},
- {OpenACCClauseKind::If, llvm::acc::Clause::ACCC_if},
- {OpenACCClauseKind::Self, llvm::acc::Clause::ACCC_self},
- {OpenACCClauseKind::Copy, llvm::acc::Clause::ACCC_copy},
- {OpenACCClauseKind::PCopy, llvm::acc::Clause::ACCC_copy},
- {OpenACCClauseKind::PresentOrCopy, llvm::acc::Clause::ACCC_copy},
- {OpenACCClauseKind::UseDevice, llvm::acc::Clause::ACCC_use_device},
- {OpenACCClauseKind::Attach, llvm::acc::Clause::ACCC_attach},
- {OpenACCClauseKind::Delete, llvm::acc::Clause::ACCC_delete},
- {OpenACCClauseKind::Detach, llvm::acc::Clause::ACCC_detach},
- {OpenACCClauseKind::Device, llvm::acc::Clause::ACCC_device},
- {OpenACCClauseKind::DevicePtr, llvm::acc::Clause::ACCC_deviceptr},
- {OpenACCClauseKind::DeviceResident,
- llvm::acc::Clause::ACCC_device_resident},
- {OpenACCClauseKind::FirstPrivate, llvm::acc::Clause::ACCC_firstprivate},
- {OpenACCClauseKind::Host, llvm::acc::Clause::ACCC_host},
- {OpenACCClauseKind::Link, llvm::acc::Clause::ACCC_link},
- {OpenACCClauseKind::NoCreate, llvm::acc::Clause::ACCC_no_create},
- {OpenACCClauseKind::Present, llvm::acc::Clause::ACCC_present},
- {OpenACCClauseKind::Private, llvm::acc::Clause::ACCC_private},
- {OpenACCClauseKind::CopyOut, llvm::acc::Clause::ACCC_copyout},
- {OpenACCClauseKind::PCopyOut, llvm::acc::Clause::ACCC_copyout},
- {OpenACCClauseKind::PresentOrCopyOut, llvm::acc::Clause::ACCC_copyout},
- {OpenACCClauseKind::CopyIn, llvm::acc::Clause::ACCC_copyin},
- {OpenACCClauseKind::PCopyIn, llvm::acc::Clause::ACCC_copyin},
- {OpenACCClauseKind::PresentOrCopyIn, llvm::acc::Clause::ACCC_copyin},
- {OpenACCClauseKind::Create, llvm::acc::Clause::ACCC_create},
- {OpenACCClauseKind::PCreate, llvm::acc::Clause::ACCC_create},
- {OpenACCClauseKind::PresentOrCreate, llvm::acc::Clause::ACCC_create},
- {OpenACCClauseKind::Reduction, llvm::acc::Clause::ACCC_reduction},
- {OpenACCClauseKind::Collapse, llvm::acc::Clause::ACCC_collapse},
- {OpenACCClauseKind::Bind, llvm::acc::Clause::ACCC_bind},
- {OpenACCClauseKind::VectorLength, llvm::acc::Clause::ACCC_vector_length},
- {OpenACCClauseKind::NumGangs, llvm::acc::Clause::ACCC_num_gangs},
- {OpenACCClauseKind::NumWorkers, llvm::acc::Clause::ACCC_num_workers},
- {OpenACCClauseKind::DeviceNum, llvm::acc::Clause::ACCC_device_num},
- {OpenACCClauseKind::DefaultAsync, llvm::acc::Clause::ACCC_default_async},
- {OpenACCClauseKind::DeviceType, llvm::acc::Clause::ACCC_device_type},
- {OpenACCClauseKind::DType, llvm::acc::Clause::ACCC_device_type},
- {OpenACCClauseKind::Async, llvm::acc::Clause::ACCC_async},
- {OpenACCClauseKind::Tile, llvm::acc::Clause::ACCC_tile},
- {OpenACCClauseKind::Gang, llvm::acc::Clause::ACCC_gang},
- {OpenACCClauseKind::Wait, llvm::acc::Clause::ACCC_wait}};
-
-llvm::acc::Clause getLLVMClauseFromClangClause(OpenACCClauseKind CK) {
- assert(CK != OpenACCClauseKind::Invalid);
-
- auto *Res =
- llvm::find_if(ClauseEquivs, [=](auto Ref) { return CK == Ref.first; });
- assert(Res && "Unhandled clause kind");
-
- return Res->second;
-}
+} // namespace
-OpenACCClauseKind getClangClauseFromLLVMClause(llvm::acc::Clause CK) {
+// TODO: ERICH: WOULD NEED Own DIRECTIVE_CLAUSE_SETS
+#define GEN_CLANG_DIRECTIVE_CLAUSE_SETS
+#include "llvm/Frontend/OpenACC/ACC.inc"
- auto *Res =
- llvm::find_if(ClauseEquivs, [=](auto Ref) { return CK == Ref.second; });
- assert(Res && "Unhandled clause kind");
+namespace {
- return Res->first;
-}
+// TODO: ERIHC: WOULD NEED ON DIRECTIVE_CLAUSE_MAP
+LLVMDirectiveClauseRelationships Relations[] =
+#define GEN_CLANG_DIRECTIVE_CLAUSE_MAP
+#include "llvm/Frontend/OpenACC/ACC.inc"
+ ;
const LLVMClauseLists &getListsForDirective(OpenACCDirectiveKind DK) {
@@ -220,13 +97,13 @@ std::string getListOfClauses(AccClauseSet Set) {
std::string Output;
llvm::raw_string_ostream OS{Output};
- for (unsigned I = 0; I < llvm::acc::Clause_enumSize; ++I) {
- llvm::acc::Clause CurClause = static_cast<llvm::acc::Clause>(I);
+ for (unsigned I = 0; I < static_cast<unsigned>(OpenACCClauseKind::Invalid);
+ ++I) {
+ OpenACCClauseKind CurClause = static_cast<OpenACCClauseKind>(I);
if (!Set.isSet(CurClause))
continue;
- OpenACCClauseKind NewCK = getClangClauseFromLLVMClause(CurClause);
- OS << '\'' << NewCK << '\'';
+ OS << '\'' << CurClause << '\'';
Set.clearBit(CurClause);
@@ -259,7 +136,7 @@ bool SemaOpenACC::DiagnoseRequiredClauses(
return false;
for (auto *C : Clauses) {
- if (Lists.Required.isSet(getLLVMClauseFromClangClause(C->getClauseKind())))
+ if (Lists.Required.isSet(C->getClauseKind()))
return false;
}
@@ -277,9 +154,7 @@ bool SemaOpenACC::DiagnoseAllowedOnceClauses(
return false;
const LLVMClauseLists &Lists = getListsForDirective(DK);
- llvm::acc::Clause LLVMClause = getLLVMClauseFromClangClause(CK);
-
- if (!Lists.AllowedOnce.isSet(LLVMClause))
+ if (!Lists.AllowedOnce.isSet(CK))
return false;
auto Res = llvm::find_if(Clauses, [=](const OpenACCClause *C) {
@@ -302,17 +177,14 @@ bool SemaOpenACC::DiagnoseExclusiveClauses(
if (DK == OpenACCDirectiveKind::Invalid || CK == OpenACCClauseKind::Invalid)
return false;
- llvm::acc::Clause LLVMClause = getLLVMClauseFromClangClause(CK);
const LLVMClauseLists &Lists = getListsForDirective(DK);
// If this isn't on the list, this is fine.
- if (!Lists.AllowedExclusive.isSet(LLVMClause))
+ if (!Lists.AllowedExclusive.isSet(CK))
return false;
for (const OpenACCClause *C : Clauses) {
- llvm::acc::Clause ExistingLLVMClause =
- getLLVMClauseFromClangClause(C->getClauseKind());
- if (Lists.AllowedExclusive.isSet(ExistingLLVMClause)) {
+ if (Lists.AllowedExclusive.isSet(C->getClauseKind())) {
Diag(ClauseLoc, diag::err_acc_clause_cannot_combine)
<< CK << C->getClauseKind() << DK;
Diag(C->getBeginLoc(), diag::note_acc_previous_clause_here);
@@ -331,10 +203,9 @@ bool SemaOpenACC::DiagnoseAllowedClauses(OpenACCDirectiveKind DK,
if (DK == OpenACCDirectiveKind::Invalid || CK == OpenACCClauseKind::Invalid)
return false;
const LLVMClauseLists &Lists = getListsForDirective(DK);
- llvm::acc::Clause Clause = getLLVMClauseFromClangClause(CK);
- if (!Lists.Allowed.isSet(Clause) && !Lists.AllowedOnce.isSet(Clause) &&
- !Lists.AllowedExclusive.isSet(Clause) && !Lists.Required.isSet(Clause))
+ if (!Lists.Allowed.isSet(CK) && !Lists.AllowedOnce.isSet(CK) &&
+ !Lists.AllowedExclusive.isSet(CK) && !Lists.Required.isSet(CK))
return Diag(ClauseLoc, diag::err_acc_clause_appertainment) << DK << CK;
return false;
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index ab68e028f1e96..70facf4b0b1cf 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -1072,6 +1072,14 @@ static void generateFlangClausesParser(const DirectiveLanguage &DirLang,
OS << ")\n";
}
+// Generate the implementation section for the enumeration in the directive
+// language
+static void emitDirectivesClangImpl(const DirectiveLanguage &DirLang,
+ raw_ostream &OS) {
+ // Currently we only have work to do for OpenACC, so skip.
+ if (DirLang.getName() != "OpenACC")
+ return;
+}
// Generate the implementation section for the enumeration in the directive
// language
static void emitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
@@ -1211,6 +1219,8 @@ static void emitDirectivesImpl(const RecordKeeper &Records, raw_ostream &OS) {
emitDirectivesFlangImpl(DirLang, OS);
+ emitDirectivesClangImpl(DirLang, OS);
+
generateClauseClassMacro(DirLang, OS);
emitDirectivesBasicImpl(DirLang, OS);
>From ff1a7bddd9435b6ae2890c07eae60bb07898bbf5 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Apr 2025 10:27:56 -0700
Subject: [PATCH 4/7] Modify tablegen to emit something clang can just consume.
In an attempt to reduce the amount of hackery that clang had to do, I've
added some tablegen stuff. There is some things that are perhaps not
well isolated, but hopefully this'll improve the codebase at least a
little.
---
clang/include/clang/Basic/OpenACCKinds.h | 8 ++
clang/lib/AST/TextNodeDumper.cpp | 1 +
clang/lib/Parse/ParseOpenACC.cpp | 2 +
clang/lib/Sema/SemaOpenACCClause.cpp | 2 +
.../Sema/SemaOpenACCClauseAppertainment.cpp | 10 +-
clang/lib/Serialization/ASTReader.cpp | 1 +
clang/lib/Serialization/ASTWriter.cpp | 1 +
.../llvm/Frontend/Directive/DirectiveBase.td | 4 +
llvm/include/llvm/Frontend/OpenACC/ACC.td | 8 +-
llvm/include/llvm/TableGen/DirectiveEmitter.h | 47 +++++++++
.../utils/TableGen/Basic/DirectiveEmitter.cpp | 98 ++++++++++++++-----
11 files changed, 153 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index e9f0e657e6f7c..5cf43ee353622 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -328,6 +328,11 @@ enum class OpenACCClauseKind : uint8_t {
/// constructs.
Wait,
+ /// 'shortloop' is represented in the ACC.td file, but isn't present in the
+ /// standard. This appears to be an old extension for the nvidia fortran
+ // compiler, but seemingly not elsewhere. Put it here as a placeholder, but it
+ // is never expected to be generated.
+ Shortloop,
/// Represents an invalid clause, for the purposes of parsing. Should be
/// 'last'.
Invalid,
@@ -486,6 +491,9 @@ inline StreamTy &printOpenACCClauseKind(StreamTy &Out, OpenACCClauseKind K) {
case OpenACCClauseKind::Wait:
return Out << "wait";
+ case OpenACCClauseKind::Shortloop:
+ llvm_unreachable("Shortloop shouldn't be generated in clang");
+ LLVM_FALLTHROUGH;
case OpenACCClauseKind::Invalid:
return Out << "<invalid>";
}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index be8d609974d81..85db20046e566 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -433,6 +433,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Vector:
case OpenACCClauseKind::VectorLength:
case OpenACCClauseKind::Invalid:
+ case OpenACCClauseKind::Shortloop:
// The condition expression will be printed as a part of the 'children',
// but print 'clause' here so it is clear what is happening from the dump.
OS << " clause";
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 64916995907c5..18ee0a71a00c5 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -536,6 +536,8 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
case OpenACCClauseKind::Tile:
return ClauseParensKind::Required;
+ case OpenACCClauseKind::Shortloop:
+ llvm_unreachable("Shortloop shouldn't be generated in clang");
case OpenACCClauseKind::Auto:
case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp
index edf9cb36b59d1..ff321b8beb073 100644
--- a/clang/lib/Sema/SemaOpenACCClause.cpp
+++ b/clang/lib/Sema/SemaOpenACCClause.cpp
@@ -215,6 +215,8 @@ class SemaOpenACCClauseVisitor {
return nullptr;
switch (Clause.getClauseKind()) {
+ case OpenACCClauseKind::Shortloop:
+ llvm_unreachable("Shortloop shouldn't be generated in clang");
case OpenACCClauseKind::Invalid:
return nullptr;
#define VISIT_CLAUSE(CLAUSE_NAME) \
diff --git a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
index ce6ca4b8d6888..a07ce6481a7f5 100644
--- a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
+++ b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
@@ -26,7 +26,7 @@ namespace {
class AccClauseSet {
// We're just using a uint64_t as our underlying rep, so if this size ever
// gets bigger than 64, we probably need a pair of uint64_ts.
- static_assert(static_assert<unsigned>(OpenACCClauseKind::Invalid) < 64);
+ static_assert(static_cast<unsigned>(OpenACCClauseKind::Invalid) < 64);
uint64_t Data;
void setBit(OpenACCClauseKind C) {
@@ -61,13 +61,14 @@ struct LLVMClauseLists {
AccClauseSet Required;
};
struct LLVMDirectiveClauseRelationships {
- llvm::acc::Directive DirKind;
+ OpenACCDirectiveKind DirKind;
LLVMClauseLists Lists;
};
} // namespace
-// TODO: ERICH: WOULD NEED Own DIRECTIVE_CLAUSE_SETS
+// This introduces these in a llvm::acc namespace, so make sure this stays in
+// the global namespace.
#define GEN_CLANG_DIRECTIVE_CLAUSE_SETS
#include "llvm/Frontend/OpenACC/ACC.inc"
@@ -81,10 +82,9 @@ LLVMDirectiveClauseRelationships Relations[] =
const LLVMClauseLists &getListsForDirective(OpenACCDirectiveKind DK) {
- llvm::acc::Directive Dir = getLLVMDirectiveFromClangDirective(DK);
auto Res = llvm::find_if(Relations,
[=](const LLVMDirectiveClauseRelationships &Rel) {
- return Rel.DirKind == Dir;
+ return Rel.DirKind == DK;
});
assert(Res != std::end(Relations) && "Unknown directive kind?");
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 38c49844848f5..3aaf7f5237a69 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -12897,6 +12897,7 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
return OpenACCBindClause::Create(getContext(), BeginLoc, LParenLoc,
readIdentifier(), EndLoc);
}
+ case OpenACCClauseKind::Shortloop:
case OpenACCClauseKind::Invalid:
llvm_unreachable("Clause serialization not yet implemented");
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a48c05061626a..cd6757c96765e 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -8860,6 +8860,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
return;
}
case OpenACCClauseKind::Invalid:
+ case OpenACCClauseKind::Shortloop:
llvm_unreachable("Clause serialization not yet implemented");
}
llvm_unreachable("Invalid Clause Kind");
diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
index 707239c7ba364..87ce80846dd93 100644
--- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
+++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
@@ -113,6 +113,10 @@ class Clause<string c> {
// Set the prefix as optional.
// `clause([prefix]: value)`
bit isPrefixOptional = true;
+
+ // When necessary because it isn't covered by rules, the name used in the
+ // clause in the clang::OpenACCClauseKind enum.
+ string clangAccSpelling = "";
}
// Hold information about clause validity by version.
diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
index f3eefb52fc46d..f39005fe7adbe 100644
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -68,12 +68,14 @@ def ACCC_Copy : Clause<"copy"> {
// 2.7.7
def ACCC_Copyin : Clause<"copyin"> {
let flangClass = "AccObjectListWithModifier";
+ let clangAccSpelling = "CopyIn";
let aliases = ["present_or_copyin", "pcopyin"];
}
// 2.7.8
def ACCC_Copyout : Clause<"copyout"> {
let flangClass = "AccObjectListWithModifier";
+ let clangAccSpelling = "CopyOut";
let aliases = ["present_or_copyout", "pcopyout"];
}
@@ -124,6 +126,7 @@ def ACCC_DeviceNum : Clause<"device_num"> {
// 2.7.4
def ACCC_DevicePtr : Clause<"deviceptr"> {
let flangClass = "AccObjectList";
+ let clangAccSpelling = "DevicePtr";
}
// 2.13.1
@@ -144,6 +147,7 @@ def ACCC_Finalize : Clause<"finalize"> {}
// 2.5.14
def ACCC_FirstPrivate : Clause<"firstprivate"> {
let flangClass = "AccObjectList";
+ let clangAccSpelling = "FirstPrivate";
}
// 2.9.2
@@ -179,7 +183,9 @@ def ACCC_NoCreate : Clause<"no_create"> {
}
// 2.15.1
-def ACCC_NoHost : Clause<"nohost"> {}
+def ACCC_NoHost : Clause<"nohost"> {
+ let clangAccSpelling = "NoHost";
+}
// 2.5.10
def ACCC_NumGangs : Clause<"num_gangs"> {
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index a2c9b2d427cce..efb1b3bdfb382 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -160,6 +160,29 @@ class Directive : public BaseRecord {
}
const Record *getCategory() const { return Def->getValueAsDef("category"); }
+
+ // Clang uses a different format for names of its directives enum.
+ std::string getClangAccSpelling() const {
+ std::string Name = Def->getValueAsString("name").str();
+
+ // Clang calls the 'unknown' value 'invalid'.
+ if (Name == "unknown") return "Invalid";
+
+ // Clang entries all start with a capital letter, so apply that.
+ Name[0] = std::toupper(Name[0]);
+ // Additionally, spaces/underscores are handled by capitalizing the next
+ // letter of the name and removing the space/underscore.
+ for (unsigned I = 0; I < Name.size(); ++I) {
+ if (Name[I] == ' ' || Name[I] == '_') {
+ Name.erase(I, 1);
+ assert(Name[I] != ' ' && Name[I] != '_' &&
+ "No double spaces/underscores");
+ Name[I] = std::toupper(Name[I]);
+ }
+ }
+
+ return Name;
+ }
};
// Wrapper class that contains Clause's information defined in DirectiveBase.td
@@ -200,6 +223,30 @@ class Clause : public BaseRecord {
return N;
}
+ // Clang uses a different format for names of its clause enum, which can be
+ // overwritten with the `clangSpelling` value. So get the proper spelling
+ // here.
+ std::string getClangAccSpelling() const {
+ if (StringRef ClangSpelling = Def->getValueAsString("clangAccSpelling");
+ !ClangSpelling.empty())
+ return ClangSpelling.str();
+
+ std::string Name = Def->getValueAsString("name").str();
+ // Clang entries all start with a capital letter, so apply that.
+ Name[0] = std::toupper(Name[0]);
+ // Additionally, underscores are handled by capitalizing the next letter of
+ // the name and removing the underscore.
+ for (unsigned I = 0; I < Name.size(); ++I) {
+ if (Name[I] == '_') {
+ Name.erase(I, 1);
+ assert(Name[I] != '_' && "No double underscores");
+ Name[I] = std::toupper(Name[I]);
+ }
+ }
+
+ return Name;
+ }
+
// Optional field.
StringRef getEnumName() const {
return Def->getValueAsString("enumClauseValue");
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 70facf4b0b1cf..1ae666523d3d5 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -759,10 +759,25 @@ static void generateGetDirectiveCategory(const DirectiveLanguage &DirLang,
OS << "}\n";
}
+namespace {
+enum class DirectiveClauseFE { Flang, Clang };
+
+StringRef getFESpelling(DirectiveClauseFE FE) {
+ switch (FE) {
+ case DirectiveClauseFE::Flang:
+ return "flang";
+ case DirectiveClauseFE::Clang:
+ return "clang";
+ }
+ llvm_unreachable("unknown FE kind");
+}
+} // namespace
+
// Generate a simple enum set with the give clauses.
static void generateClauseSet(ArrayRef<const Record *> Clauses, raw_ostream &OS,
StringRef ClauseSetPrefix, const Directive &Dir,
- const DirectiveLanguage &DirLang) {
+ const DirectiveLanguage &DirLang,
+ DirectiveClauseFE FE) {
OS << "\n";
OS << " static " << DirLang.getClauseEnumSetClass() << " " << ClauseSetPrefix
@@ -770,21 +785,36 @@ static void generateClauseSet(ArrayRef<const Record *> Clauses, raw_ostream &OS,
for (const auto &C : Clauses) {
VersionedClause VerClause(C);
+ if (FE == DirectiveClauseFE::Flang) {
OS << " llvm::" << DirLang.getCppNamespace()
<< "::Clause::" << DirLang.getClausePrefix()
<< VerClause.getClause().getFormattedName() << ",\n";
+ } else {
+ assert(FE == DirectiveClauseFE::Clang);
+ assert(DirLang.getName() == "OpenACC");
+ OS << " clang::OpenACCClauseKind::"
+ << VerClause.getClause().getClangAccSpelling() << ",\n";
+ }
}
OS << " };\n";
}
// Generate an enum set for the 4 kinds of clauses linked to a directive.
static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
+ DirectiveClauseFE FE,
raw_ostream &OS) {
- IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS);
+ std::string IfDefName{"GEN_"};
+ IfDefName += getFESpelling(FE).upper();
+ IfDefName += "_DIRECTIVE_CLAUSE_SETS";
+ IfDefScope Scope(IfDefName, OS);
OS << "\n";
- OS << "namespace llvm {\n";
+ // The namespace has to be different for clang vs flang, as 2 structs with the
+ // same name but different layout is UB. So just put the 'clang' on in the
+ // clang namespace.
+ OS << "namespace " << (FE == DirectiveClauseFE::Flang ? "llvm" : "clang")
+ << "{\n";
// Open namespaces defined in the directive language.
SmallVector<StringRef, 2> Namespaces;
@@ -797,13 +827,13 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
OS << " // Sets for " << Dir.getName() << "\n";
generateClauseSet(Dir.getAllowedClauses(), OS, "allowedClauses_", Dir,
- DirLang);
+ DirLang, FE);
generateClauseSet(Dir.getAllowedOnceClauses(), OS, "allowedOnceClauses_",
- Dir, DirLang);
+ Dir, DirLang, FE);
generateClauseSet(Dir.getAllowedExclusiveClauses(), OS,
- "allowedExclusiveClauses_", Dir, DirLang);
+ "allowedExclusiveClauses_", Dir, DirLang, FE);
generateClauseSet(Dir.getRequiredClauses(), OS, "requiredClauses_", Dir,
- DirLang);
+ DirLang, FE);
}
// Closing namespaces
@@ -817,27 +847,46 @@ static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
// The struct holds the 4 sets of enumeration for the 4 kinds of clauses
// allowances (allowed, allowed once, allowed exclusive and required).
static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
- raw_ostream &OS) {
-
- IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS);
+ DirectiveClauseFE FE, raw_ostream &OS) {
+ std::string IfDefName{"GEN_"};
+ IfDefName += getFESpelling(FE).upper();
+ IfDefName += "_DIRECTIVE_CLAUSE_MAP";
+ IfDefScope Scope(IfDefName, OS);
OS << "\n";
OS << "{\n";
+ // The namespace has to be different for clang vs flang, as 2 structs with the
+ // same name but different layout is UB. So just put the 'clang' on in the
+ // clang namespace.
+ StringRef TopLevelNS = (FE == DirectiveClauseFE::Flang ? "llvm" : "clang");
+
for (const Directive Dir : DirLang.getDirectives()) {
- OS << " {llvm::" << DirLang.getCppNamespace()
- << "::Directive::" << DirLang.getDirectivePrefix()
- << Dir.getFormattedName() << ",\n";
+ OS << " {";
+ if (FE == DirectiveClauseFE::Flang) {
+ OS << TopLevelNS << "::" << DirLang.getCppNamespace()
+ << "::Directive::" << DirLang.getDirectivePrefix()
+ << Dir.getFormattedName() << ",\n";
+ } else {
+ assert(FE == DirectiveClauseFE::Clang);
+ assert(DirLang.getName() == "OpenACC");
+ OS << "clang::OpenACCDirectiveKind::" << Dir.getClangAccSpelling()
+ << ",\n";
+ }
+
OS << " {\n";
- OS << " llvm::" << DirLang.getCppNamespace() << "::allowedClauses_"
- << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n";
- OS << " llvm::" << DirLang.getCppNamespace() << "::allowedOnceClauses_"
- << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n";
- OS << " llvm::" << DirLang.getCppNamespace()
+ OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
+ << "::allowedClauses_" << DirLang.getDirectivePrefix()
+ << Dir.getFormattedName() << ",\n";
+ OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
+ << "::allowedOnceClauses_" << DirLang.getDirectivePrefix()
+ << Dir.getFormattedName() << ",\n";
+ OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
<< "::allowedExclusiveClauses_" << DirLang.getDirectivePrefix()
<< Dir.getFormattedName() << ",\n";
- OS << " llvm::" << DirLang.getCppNamespace() << "::requiredClauses_"
- << DirLang.getDirectivePrefix() << Dir.getFormattedName() << ",\n";
+ OS << " " << TopLevelNS << "::" << DirLang.getCppNamespace()
+ << "::requiredClauses_" << DirLang.getDirectivePrefix()
+ << Dir.getFormattedName() << ",\n";
OS << " }\n";
OS << " },\n";
}
@@ -1076,17 +1125,20 @@ static void generateFlangClausesParser(const DirectiveLanguage &DirLang,
// language
static void emitDirectivesClangImpl(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- // Currently we only have work to do for OpenACC, so skip.
+ // Currently we only have work to do for OpenACC, so skip otherwise.
if (DirLang.getName() != "OpenACC")
return;
+
+ generateDirectiveClauseSets(DirLang, DirectiveClauseFE::Clang, OS);
+ generateDirectiveClauseMap(DirLang, DirectiveClauseFE::Clang, OS);
}
// Generate the implementation section for the enumeration in the directive
// language
static void emitDirectivesFlangImpl(const DirectiveLanguage &DirLang,
raw_ostream &OS) {
- generateDirectiveClauseSets(DirLang, OS);
+ generateDirectiveClauseSets(DirLang, DirectiveClauseFE::Flang, OS);
- generateDirectiveClauseMap(DirLang, OS);
+ generateDirectiveClauseMap(DirLang, DirectiveClauseFE::Flang, OS);
generateFlangClauseParserClass(DirLang, OS);
>From b596122e37fd84792c4f7fc4e8f45af657b4bc9a Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Apr 2025 10:31:23 -0700
Subject: [PATCH 5/7] Clang-format for tablegen changes
---
llvm/include/llvm/TableGen/DirectiveEmitter.h | 3 ++-
llvm/utils/TableGen/Basic/DirectiveEmitter.cpp | 13 ++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/TableGen/DirectiveEmitter.h b/llvm/include/llvm/TableGen/DirectiveEmitter.h
index efb1b3bdfb382..28373271ef1e8 100644
--- a/llvm/include/llvm/TableGen/DirectiveEmitter.h
+++ b/llvm/include/llvm/TableGen/DirectiveEmitter.h
@@ -166,7 +166,8 @@ class Directive : public BaseRecord {
std::string Name = Def->getValueAsString("name").str();
// Clang calls the 'unknown' value 'invalid'.
- if (Name == "unknown") return "Invalid";
+ if (Name == "unknown")
+ return "Invalid";
// Clang entries all start with a capital letter, so apply that.
Name[0] = std::toupper(Name[0]);
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 1ae666523d3d5..9071bff4ee3d7 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -786,9 +786,9 @@ static void generateClauseSet(ArrayRef<const Record *> Clauses, raw_ostream &OS,
for (const auto &C : Clauses) {
VersionedClause VerClause(C);
if (FE == DirectiveClauseFE::Flang) {
- OS << " llvm::" << DirLang.getCppNamespace()
- << "::Clause::" << DirLang.getClausePrefix()
- << VerClause.getClause().getFormattedName() << ",\n";
+ OS << " llvm::" << DirLang.getCppNamespace()
+ << "::Clause::" << DirLang.getClausePrefix()
+ << VerClause.getClause().getFormattedName() << ",\n";
} else {
assert(FE == DirectiveClauseFE::Clang);
assert(DirLang.getName() == "OpenACC");
@@ -801,8 +801,7 @@ static void generateClauseSet(ArrayRef<const Record *> Clauses, raw_ostream &OS,
// Generate an enum set for the 4 kinds of clauses linked to a directive.
static void generateDirectiveClauseSets(const DirectiveLanguage &DirLang,
- DirectiveClauseFE FE,
- raw_ostream &OS) {
+ DirectiveClauseFE FE, raw_ostream &OS) {
std::string IfDefName{"GEN_"};
IfDefName += getFESpelling(FE).upper();
@@ -865,8 +864,8 @@ static void generateDirectiveClauseMap(const DirectiveLanguage &DirLang,
OS << " {";
if (FE == DirectiveClauseFE::Flang) {
OS << TopLevelNS << "::" << DirLang.getCppNamespace()
- << "::Directive::" << DirLang.getDirectivePrefix()
- << Dir.getFormattedName() << ",\n";
+ << "::Directive::" << DirLang.getDirectivePrefix()
+ << Dir.getFormattedName() << ",\n";
} else {
assert(FE == DirectiveClauseFE::Clang);
assert(DirLang.getName() == "OpenACC");
>From 73763be600f396441a7157d4c30a53690723c677 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Apr 2025 10:59:42 -0700
Subject: [PATCH 6/7] Dealias clauses correctly, which should eliminate
failures after tablegen. Also, sort the clause kind list so that diagnostics
are alphabetical
---
clang/include/clang/Basic/OpenACCKinds.h | 159 +++++++++---------
.../Sema/SemaOpenACCClauseAppertainment.cpp | 33 +++-
2 files changed, 105 insertions(+), 87 deletions(-)
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 5cf43ee353622..a798401dfa9f5 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -202,32 +202,21 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
return printOpenACCAtomicKind(Out, AK);
}
-/// Represents the kind of an OpenACC clause.
+/// Represents the kind of an OpenACC clause. Sorted alphabetically, since this
+/// order ends up influencing the sorting of the list diagnostic.
enum class OpenACCClauseKind : uint8_t {
- /// 'finalize' clause, allowed on 'exit data' directive.
- Finalize,
- /// 'if_present' clause, allowed on 'host_data' and 'update' directives.
- IfPresent,
- /// 'seq' clause, allowed on 'loop' and 'routine' directives.
- Seq,
- /// 'independent' clause, allowed on 'loop' directives.
- Independent,
+ /// 'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined
+ /// constructs.
+ Async,
+ /// 'attach' clause, allowed on Compute and Combined constructs, plus 'data'
+ /// and 'enter data'.
+ Attach,
/// 'auto' clause, allowed on 'loop' directives.
Auto,
- /// 'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
- Worker,
- /// 'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
- Vector,
- /// 'nohost' clause, allowed on 'routine' directives.
- NoHost,
- /// 'default' clause, allowed on parallel, serial, kernel (and compound)
- /// constructs.
- Default,
- /// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
- /// Executable Constructs, and Combined Constructs.
- If,
- /// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
- Self,
+ /// 'bind' clause, allowed on routine constructs.
+ Bind,
+ /// 'collapse' clause, allowed on 'loop' and Combined constructs.
+ Collapse,
/// 'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and
/// 'declare'.
Copy,
@@ -235,98 +224,110 @@ enum class OpenACCClauseKind : uint8_t {
PCopy,
/// 'copy' clause alias 'present_or_copy'. Preserved for diagnostic purposes.
PresentOrCopy,
- /// 'use_device' clause, allowed on 'host_data' construct.
- UseDevice,
- /// 'attach' clause, allowed on Compute and Combined constructs, plus 'data'
- /// and 'enter data'.
- Attach,
+ /// 'copyin' clause, allowed on Compute and Combined constructs, plus 'data',
+ /// 'enter data', and 'declare'.
+ CopyIn,
+ /// 'copyin' clause alias 'pcopyin'. Preserved for diagnostic purposes.
+ PCopyIn,
+ /// 'copyin' clause alias 'present_or_copyin'. Preserved for diagnostic
+ /// purposes.
+ PresentOrCopyIn,
+ /// 'copyout' clause, allowed on Compute and Combined constructs, plus 'data',
+ /// 'exit data', and 'declare'.
+ CopyOut,
+ /// 'copyout' clause alias 'pcopyout'. Preserved for diagnostic purposes.
+ PCopyOut,
+ /// 'copyout' clause alias 'present_or_copyout'. Preserved for diagnostic
+ /// purposes.
+ PresentOrCopyOut,
+ /// 'create' clause, allowed on Compute and Combined constructs, plus 'data',
+ /// 'enter data', and 'declare'.
+ Create,
+ /// 'create' clause alias 'pcreate'. Preserved for diagnostic purposes.
+ PCreate,
+ /// 'create' clause alias 'present_or_create'. Preserved for diagnostic
+ /// purposes.
+ PresentOrCreate,
+ /// 'default' clause, allowed on parallel, serial, kernel (and compound)
+ /// constructs.
+ Default,
+ /// 'default_async' clause, allowed on 'set' construct.
+ DefaultAsync,
/// 'delete' clause, allowed on the 'exit data' construct.
Delete,
/// 'detach' clause, allowed on the 'exit data' construct.
Detach,
/// 'device' clause, allowed on the 'update' construct.
Device,
+ /// 'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
+ DeviceNum,
/// 'deviceptr' clause, allowed on Compute and Combined Constructs, plus
/// 'data' and 'declare'.
DevicePtr,
/// 'device_resident' clause, allowed on the 'declare' construct.
DeviceResident,
+ /// 'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown',
+ /// 'set', update', 'loop', 'routine', and Combined constructs.
+ DeviceType,
+ /// 'dtype' clause, an alias for 'device_type', stored separately for
+ /// diagnostic purposes.
+ DType,
+ /// 'finalize' clause, allowed on 'exit data' directive.
+ Finalize,
/// 'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop',
/// and 'serial loop' constructs.
FirstPrivate,
+ /// 'gang' clause, allowed on 'loop' and Combined constructs.
+ Gang,
/// 'host' clause, allowed on 'update' construct.
Host,
+ /// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
+ /// Executable Constructs, and Combined Constructs.
+ If,
+ /// 'if_present' clause, allowed on 'host_data' and 'update' directives.
+ IfPresent,
+ /// 'independent' clause, allowed on 'loop' directives.
+ Independent,
/// 'link' clause, allowed on 'declare' construct.
Link,
/// 'no_create' clause, allowed on allowed on Compute and Combined constructs,
/// plus 'data'.
NoCreate,
+ /// 'nohost' clause, allowed on 'routine' directives.
+ NoHost,
+ /// 'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and
+ /// 'kernels loop' constructs.
+ NumGangs,
+ /// 'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop',
+ /// and 'kernels loop' constructs.
+ NumWorkers,
/// 'present' clause, allowed on Compute and Combined constructs, plus 'data'
/// and 'declare'.
Present,
/// 'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel
/// loop', and 'serial loop' constructs.
Private,
- /// 'copyout' clause, allowed on Compute and Combined constructs, plus 'data',
- /// 'exit data', and 'declare'.
- CopyOut,
- /// 'copyout' clause alias 'pcopyout'. Preserved for diagnostic purposes.
- PCopyOut,
- /// 'copyout' clause alias 'present_or_copyout'. Preserved for diagnostic
- /// purposes.
- PresentOrCopyOut,
- /// 'copyin' clause, allowed on Compute and Combined constructs, plus 'data',
- /// 'enter data', and 'declare'.
- CopyIn,
- /// 'copyin' clause alias 'pcopyin'. Preserved for diagnostic purposes.
- PCopyIn,
- /// 'copyin' clause alias 'present_or_copyin'. Preserved for diagnostic
- /// purposes.
- PresentOrCopyIn,
- /// 'create' clause, allowed on Compute and Combined constructs, plus 'data',
- /// 'enter data', and 'declare'.
- Create,
- /// 'create' clause alias 'pcreate'. Preserved for diagnostic purposes.
- PCreate,
- /// 'create' clause alias 'present_or_create'. Preserved for diagnostic
- /// purposes.
- PresentOrCreate,
/// 'reduction' clause, allowed on Parallel, Serial, Loop, and the combined
/// constructs.
Reduction,
- /// 'collapse' clause, allowed on 'loop' and Combined constructs.
- Collapse,
- /// 'bind' clause, allowed on routine constructs.
- Bind,
+ /// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
+ Self,
+ /// 'seq' clause, allowed on 'loop' and 'routine' directives.
+ Seq,
+ /// 'tile' clause, allowed on 'loop' and Combined constructs.
+ Tile,
+ /// 'use_device' clause, allowed on 'host_data' construct.
+ UseDevice,
+ /// 'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
+ Vector,
/// 'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop',
/// and 'kernels loop' constructs.
VectorLength,
- /// 'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and
- /// 'kernels loop' constructs.
- NumGangs,
- /// 'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop',
- /// and 'kernels loop' constructs.
- NumWorkers,
- /// 'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
- DeviceNum,
- /// 'default_async' clause, allowed on 'set' construct.
- DefaultAsync,
- /// 'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown',
- /// 'set', update', 'loop', 'routine', and Combined constructs.
- DeviceType,
- /// 'dtype' clause, an alias for 'device_type', stored separately for
- /// diagnostic purposes.
- DType,
- /// 'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined
- /// constructs.
- Async,
- /// 'tile' clause, allowed on 'loop' and Combined constructs.
- Tile,
- /// 'gang' clause, allowed on 'loop' and Combined constructs.
- Gang,
/// 'wait' clause, allowed on Compute, Data, 'update', and Combined
/// constructs.
Wait,
+ /// 'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
+ Worker,
/// 'shortloop' is represented in the ACC.td file, but isn't present in the
/// standard. This appears to be an old extension for the nvidia fortran
diff --git a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
index a07ce6481a7f5..3b7747d0712cb 100644
--- a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
+++ b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
@@ -73,8 +73,6 @@ struct LLVMDirectiveClauseRelationships {
#include "llvm/Frontend/OpenACC/ACC.inc"
namespace {
-
-// TODO: ERIHC: WOULD NEED ON DIRECTIVE_CLAUSE_MAP
LLVMDirectiveClauseRelationships Relations[] =
#define GEN_CLANG_DIRECTIVE_CLAUSE_MAP
#include "llvm/Frontend/OpenACC/ACC.inc"
@@ -120,6 +118,20 @@ std::string getListOfClauses(AccClauseSet Set) {
OS.flush();
return OS.str();
}
+
+OpenACCClauseKind dealiasClauseKind(OpenACCClauseKind CK) {
+ switch (CK) {
+ default:
+ return CK;
+#define VISIT_CLAUSE(NAME)
+#define CLAUSE_ALIAS(ALIAS, NAME, DEPRECATED) \
+ case OpenACCClauseKind::ALIAS: \
+ return OpenACCClauseKind::NAME;
+#include "clang/Basic/OpenACCClauses.def"
+ }
+
+ return CK;
+}
} // namespace
// Diagnoses if `Clauses` list doesn't have at least one of the required
@@ -136,7 +148,7 @@ bool SemaOpenACC::DiagnoseRequiredClauses(
return false;
for (auto *C : Clauses) {
- if (Lists.Required.isSet(C->getClauseKind()))
+ if (Lists.Required.isSet(dealiasClauseKind(C->getClauseKind())))
return false;
}
@@ -153,12 +165,14 @@ bool SemaOpenACC::DiagnoseAllowedOnceClauses(
if (DK == OpenACCDirectiveKind::Invalid || CK == OpenACCClauseKind::Invalid)
return false;
+ OpenACCClauseKind Dealiased = dealiasClauseKind(CK);
+
const LLVMClauseLists &Lists = getListsForDirective(DK);
if (!Lists.AllowedOnce.isSet(CK))
return false;
auto Res = llvm::find_if(Clauses, [=](const OpenACCClause *C) {
- return C->getClauseKind() == CK;
+ return dealiasClauseKind(C->getClauseKind()) == Dealiased;
});
if (Res == Clauses.end())
@@ -178,13 +192,14 @@ bool SemaOpenACC::DiagnoseExclusiveClauses(
return false;
const LLVMClauseLists &Lists = getListsForDirective(DK);
+ OpenACCClauseKind Dealiased = dealiasClauseKind(CK);
// If this isn't on the list, this is fine.
- if (!Lists.AllowedExclusive.isSet(CK))
+ if (!Lists.AllowedExclusive.isSet(Dealiased))
return false;
for (const OpenACCClause *C : Clauses) {
- if (Lists.AllowedExclusive.isSet(C->getClauseKind())) {
+ if (Lists.AllowedExclusive.isSet(dealiasClauseKind(C->getClauseKind()))) {
Diag(ClauseLoc, diag::err_acc_clause_cannot_combine)
<< CK << C->getClauseKind() << DK;
Diag(C->getBeginLoc(), diag::note_acc_previous_clause_here);
@@ -203,9 +218,11 @@ bool SemaOpenACC::DiagnoseAllowedClauses(OpenACCDirectiveKind DK,
if (DK == OpenACCDirectiveKind::Invalid || CK == OpenACCClauseKind::Invalid)
return false;
const LLVMClauseLists &Lists = getListsForDirective(DK);
+ OpenACCClauseKind Dealiased = dealiasClauseKind(CK);
- if (!Lists.Allowed.isSet(CK) && !Lists.AllowedOnce.isSet(CK) &&
- !Lists.AllowedExclusive.isSet(CK) && !Lists.Required.isSet(CK))
+ if (!Lists.Allowed.isSet(Dealiased) && !Lists.AllowedOnce.isSet(Dealiased) &&
+ !Lists.AllowedExclusive.isSet(Dealiased) &&
+ !Lists.Required.isSet(Dealiased))
return Diag(ClauseLoc, diag::err_acc_clause_appertainment) << DK << CK;
return false;
>From 849315478861235dc0481d337e047245ff01e66e Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 11 Apr 2025 11:16:23 -0700
Subject: [PATCH 7/7] Clang-format
---
clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
index 3b7747d0712cb..6069c77d01676 100644
--- a/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
+++ b/clang/lib/Sema/SemaOpenACCClauseAppertainment.cpp
@@ -121,11 +121,11 @@ std::string getListOfClauses(AccClauseSet Set) {
OpenACCClauseKind dealiasClauseKind(OpenACCClauseKind CK) {
switch (CK) {
- default:
- return CK;
+ default:
+ return CK;
#define VISIT_CLAUSE(NAME)
#define CLAUSE_ALIAS(ALIAS, NAME, DEPRECATED) \
- case OpenACCClauseKind::ALIAS: \
+ case OpenACCClauseKind::ALIAS: \
return OpenACCClauseKind::NAME;
#include "clang/Basic/OpenACCClauses.def"
}
More information about the cfe-commits
mailing list