[clang] e675d0d - [OpenACC][NFC] Refactor SemaOpenACC to use a visitor
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 5 14:03:30 PDT 2024
Author: erichkeane
Date: 2024-06-05T13:27:10-07:00
New Revision: e675d0d5cd4047bcf4ec368d2b4c19a57e5347f3
URL: https://github.com/llvm/llvm-project/commit/e675d0d5cd4047bcf4ec368d2b4c19a57e5347f3
DIFF: https://github.com/llvm/llvm-project/commit/e675d0d5cd4047bcf4ec368d2b4c19a57e5347f3.diff
LOG: [OpenACC][NFC] Refactor SemaOpenACC to use a visitor
This code was getting unwieldy, so a quick patch to refactor it a bit.
Added:
Modified:
clang/include/clang/AST/OpenACCClause.h
clang/include/clang/Basic/OpenACCClauses.def
clang/lib/AST/OpenACCClause.cpp
clang/lib/Sema/SemaOpenACC.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h
index a4c82cdad87bd..ea1ffbc7fd08b 100644
--- a/clang/include/clang/AST/OpenACCClause.h
+++ b/clang/include/clang/AST/OpenACCClause.h
@@ -867,7 +867,7 @@ template <class Impl> class OpenACCClauseVisitor {
case OpenACCClauseKind::CLAUSE_NAME: \
Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \
return;
-#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME) \
+#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED) \
case OpenACCClauseKind::ALIAS_NAME: \
Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \
return;
diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def
index 53f4cd103d142..85f4859925f0b 100644
--- a/clang/include/clang/Basic/OpenACCClauses.def
+++ b/clang/include/clang/Basic/OpenACCClauses.def
@@ -15,31 +15,31 @@
//
// VISIT_CLAUSE(CLAUSE_NAME)
//
-// CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME)
+// CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED)
#ifndef CLAUSE_ALIAS
-#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME)
+#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, false)
#endif
VISIT_CLAUSE(Auto)
VISIT_CLAUSE(Async)
VISIT_CLAUSE(Attach)
VISIT_CLAUSE(Copy)
-CLAUSE_ALIAS(PCopy, Copy)
-CLAUSE_ALIAS(PresentOrCopy, Copy)
+CLAUSE_ALIAS(PCopy, Copy, true)
+CLAUSE_ALIAS(PresentOrCopy, Copy, true)
VISIT_CLAUSE(CopyIn)
-CLAUSE_ALIAS(PCopyIn, CopyIn)
-CLAUSE_ALIAS(PresentOrCopyIn, CopyIn)
+CLAUSE_ALIAS(PCopyIn, CopyIn, true)
+CLAUSE_ALIAS(PresentOrCopyIn, CopyIn, true)
VISIT_CLAUSE(CopyOut)
-CLAUSE_ALIAS(PCopyOut, CopyOut)
-CLAUSE_ALIAS(PresentOrCopyOut, CopyOut)
+CLAUSE_ALIAS(PCopyOut, CopyOut, true)
+CLAUSE_ALIAS(PresentOrCopyOut, CopyOut, true)
VISIT_CLAUSE(Create)
-CLAUSE_ALIAS(PCreate, Create)
-CLAUSE_ALIAS(PresentOrCreate, Create)
+CLAUSE_ALIAS(PCreate, Create, true)
+CLAUSE_ALIAS(PresentOrCreate, Create, true)
VISIT_CLAUSE(Default)
VISIT_CLAUSE(DevicePtr)
VISIT_CLAUSE(DeviceType)
-CLAUSE_ALIAS(DType, DeviceType)
+CLAUSE_ALIAS(DType, DeviceType, false)
VISIT_CLAUSE(FirstPrivate)
VISIT_CLAUSE(If)
VISIT_CLAUSE(Independent)
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
index 403ce9a221571..95089a9b79e26 100644
--- a/clang/lib/AST/OpenACCClause.cpp
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -104,7 +104,7 @@ OpenACCClause::child_range OpenACCClause::children() {
#define VISIT_CLAUSE(CLAUSE_NAME) \
case OpenACCClauseKind::CLAUSE_NAME: \
return cast<OpenACC##CLAUSE_NAME##Clause>(this)->children();
-#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME) \
+#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED) \
case OpenACCClauseKind::ALIAS_NAME: \
return cast<OpenACC##CLAUSE_NAME##Clause>(this)->children();
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 1320fd90b440b..97586a037eee4 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -424,617 +424,736 @@ bool checkValidAfterDeviceType(
S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here);
return true;
}
-} // namespace
-SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
+class SemaOpenACCClauseVisitor {
+ SemaOpenACC &SemaRef;
+ ASTContext &Ctx;
+ ArrayRef<const OpenACCClause *> ExistingClauses;
+ bool NotImplemented = false;
-SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(SemaOpenACC &S,
- OpenACCDirectiveKind DK)
- : SemaRef(S), WasInsideComputeConstruct(S.InsideComputeConstruct),
- DirKind(DK) {
- // Compute constructs end up taking their 'loop'.
- if (DirKind == OpenACCDirectiveKind::Parallel ||
- DirKind == OpenACCDirectiveKind::Serial ||
- DirKind == OpenACCDirectiveKind::Kernels) {
- SemaRef.InsideComputeConstruct = true;
- SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);
+ OpenACCClause *isNotImplemented() {
+ NotImplemented = true;
+ return nullptr;
}
-}
-SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
- SemaRef.InsideComputeConstruct = WasInsideComputeConstruct;
- if (DirKind == OpenACCDirectiveKind::Parallel ||
- DirKind == OpenACCDirectiveKind::Serial ||
- DirKind == OpenACCDirectiveKind::Kernels) {
- assert(SemaRef.ParentlessLoopConstructs.empty() &&
- "Didn't consume loop construct list?");
- SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);
- }
-}
+public:
+ SemaOpenACCClauseVisitor(SemaOpenACC &S,
+ ArrayRef<const OpenACCClause *> ExistingClauses)
+ : SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}
+ // Once we've implemented everything, we shouldn't need this infrastructure.
+ // But in the meantime, we use this to help decide whether the clause was
+ // handled for this directive.
+ bool diagNotImplemented() { return NotImplemented; }
+
+ OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
+ switch (Clause.getClauseKind()) {
+ case OpenACCClauseKind::Gang:
+ case OpenACCClauseKind::Worker:
+ case OpenACCClauseKind::Vector: {
+ // TODO OpenACC: These are only implemented enough for the 'seq' diagnostic,
+ // otherwise treats itself as unimplemented. When we implement these, we
+ // can remove them from here.
-OpenACCClause *
-SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
- OpenACCParsedClause &Clause) {
- if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
- return nullptr;
+ // OpenACC 3.3 2.9:
+ // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
+ // appears.
+ const auto *Itr =
+ llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
- // 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 (Itr != ExistingClauses.end()) {
+ SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
+ << Clause.getClauseKind() << (*Itr)->getClauseKind();
+ SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
+ }
+ return isNotImplemented();
}
- if (const auto *DevTypeClause =
- llvm::find_if(ExistingClauses,
- [&](const OpenACCClause *C) {
- return isa<OpenACCDeviceTypeClause>(C);
- });
- DevTypeClause != ExistingClauses.end()) {
- if (checkValidAfterDeviceType(
- *this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
- return nullptr;
+#define VISIT_CLAUSE(CLAUSE_NAME) \
+ case OpenACCClauseKind::CLAUSE_NAME: \
+ return Visit##CLAUSE_NAME##Clause(Clause);
+#define CLAUSE_ALIAS(ALIAS, CLAUSE_NAME, DEPRECATED) \
+ case OpenACCClauseKind::ALIAS: \
+ if (DEPRECATED) \
+ SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name) \
+ << Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME; \
+ return Visit##CLAUSE_NAME##Clause(Clause);
+#include "clang/Basic/OpenACCClauses.def"
+ default:
+ return isNotImplemented();
+ }
+ llvm_unreachable("Invalid clause kind");
}
- switch (Clause.getClauseKind()) {
- case OpenACCClauseKind::Default: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+#define VISIT_CLAUSE(CLAUSE_NAME) \
+ OpenACCClause *Visit##CLAUSE_NAME##Clause( \
+ SemaOpenACC::OpenACCParsedClause &Clause);
+#include "clang/Basic/OpenACCClauses.def"
+};
- // Don't add an invalid clause to the AST.
- 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(*this, ExistingClauses, Clause))
- return nullptr;
-
- return OpenACCDefaultClause::Create(
- getASTContext(), Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
- Clause.getLParenLoc(), Clause.getEndLoc());
- }
+OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // Don't add an invalid clause to the AST.
+ if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
+ return nullptr;
- case OpenACCClauseKind::If: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+ // 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;
- // 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(*this, ExistingClauses, Clause))
- return nullptr;
+ return OpenACCDefaultClause::Create(
+ Ctx, Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
+ Clause.getLParenLoc(), Clause.getEndLoc());
+}
- // The parser has ensured that we have a proper condition expr, so there
- // isn't really much to do here.
+OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // 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.
- // TODO OpenACC: When we add these two to other constructs, we might not
- // want to warn on this (for example, 'update').
- const auto *Itr =
- llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
- if (Itr != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
- Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- }
+ // The parser has ensured that we have a proper condition expr, so there
+ // isn't really much to do here.
- return OpenACCIfClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getConditionExpr(), Clause.getEndLoc());
+ // If the 'if' clause is true, it makes the 'self' clause have no effect,
+ // diagnose that here.
+ // TODO OpenACC: When we add these two to other constructs, we might not
+ // want to warn on this (for example, 'update').
+ const auto *Itr =
+ llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
+ if (Itr != ExistingClauses.end()) {
+ SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
+ SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
}
- case OpenACCClauseKind::Self: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
-
- // TODO OpenACC: When we implement this for 'update', this takes a
- // 'var-list' instead of a condition expression, so semantics/handling has
- // to happen
diff erently here.
-
- // 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(*this, ExistingClauses, Clause))
- return nullptr;
+ return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getLParenLoc(),
+ Clause.getConditionExpr(), Clause.getEndLoc());
+}
- // If the 'if' clause is true, it makes the 'self' clause have no effect,
- // diagnose that here.
- // TODO OpenACC: When we add these two to other constructs, we might not
- // want to warn on this (for example, 'update').
- const auto *Itr =
- llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);
- if (Itr != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
- Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- }
+OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // TODO OpenACC: When we implement this for 'update', this takes a
+ // 'var-list' instead of a condition expression, so semantics/handling has
+ // to happen
diff erently here.
+
+ // 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;
- return OpenACCSelfClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getConditionExpr(), Clause.getEndLoc());
+ // If the 'if' clause is true, it makes the 'self' clause have no effect,
+ // diagnose that here.
+ // TODO OpenACC: When we add these two to other constructs, we might not
+ // want to warn on this (for example, 'update').
+ const auto *Itr =
+ llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);
+ if (Itr != ExistingClauses.end()) {
+ SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
+ SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
}
- case OpenACCClauseKind::NumGangs: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+ return OpenACCSelfClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
+ Clause.getConditionExpr(), Clause.getEndLoc());
+}
- // 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(*this, ExistingClauses, Clause))
- return nullptr;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // 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 (Clause.getIntExprs().empty())
- Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
- << /*NoArgs=*/0;
-
- unsigned MaxArgs =
- (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
- Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
- ? 3
- : 1;
- if (Clause.getIntExprs().size() > MaxArgs)
- Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
- << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
+ // 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
+ // diagnostics.
+ if (Clause.getIntExprs().empty())
+ SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
+ << /*NoArgs=*/0;
+
+ unsigned MaxArgs =
+ (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
+ Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
+ ? 3
+ : 1;
+ // The max number of args
diff ers between parallel and other constructs.
+ // Again, allow us to continue for the purposes of future diagnostics.
+ if (Clause.getIntExprs().size() > MaxArgs)
+ SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
+ << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
+ << Clause.getIntExprs().size();
+
+ // OpenACC 3.3 Section 2.5.4:
+ // A reduction clause may not appear on a parallel construct with a
+ // num_gangs clause that has more than one argument.
+ if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel &&
+ Clause.getIntExprs().size() > 1) {
+ auto *Parallel =
+ llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
+
+ if (Parallel != ExistingClauses.end()) {
+ SemaRef.Diag(Clause.getBeginLoc(),
+ diag::err_acc_reduction_num_gangs_conflict)
<< Clause.getIntExprs().size();
-
- // OpenACC 3.3 Section 2.5.4:
- // A reduction clause may not appear on a parallel construct with a
- // num_gangs clause that has more than one argument.
- if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel &&
- Clause.getIntExprs().size() > 1) {
- auto *Parallel =
- llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
-
- if (Parallel != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::err_acc_reduction_num_gangs_conflict)
- << Clause.getIntExprs().size();
- Diag((*Parallel)->getBeginLoc(), diag::note_acc_previous_clause_here);
- return nullptr;
- }
+ SemaRef.Diag((*Parallel)->getBeginLoc(),
+ diag::note_acc_previous_clause_here);
+ return nullptr;
}
-
- // Create the AST node for the clause even if the number of expressions is
- // incorrect.
- return OpenACCNumGangsClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getIntExprs(), Clause.getEndLoc());
- break;
}
- case OpenACCClauseKind::NumWorkers: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+ return OpenACCNumGangsClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs(),
+ Clause.getEndLoc());
+}
- // 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(*this, ExistingClauses, Clause))
- return nullptr;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // 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.getIntExprs().size() == 1 &&
- "Invalid number of expressions for NumWorkers");
- return OpenACCNumWorkersClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getIntExprs()[0], Clause.getEndLoc());
- }
- case OpenACCClauseKind::VectorLength: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+ assert(Clause.getIntExprs().size() == 1 &&
+ "Invalid number of expressions for NumWorkers");
+ return OpenACCNumWorkersClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
+ Clause.getEndLoc());
+}
- // 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(*this, ExistingClauses, Clause))
- return nullptr;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // 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.getIntExprs().size() == 1 &&
- "Invalid number of expressions for VectorLength");
- return OpenACCVectorLengthClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getIntExprs()[0], Clause.getEndLoc());
- }
- case OpenACCClauseKind::Async: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+ assert(Clause.getIntExprs().size() == 1 &&
+ "Invalid number of expressions for NumWorkers");
+ return OpenACCVectorLengthClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
+ Clause.getEndLoc());
+}
- // 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(*this, ExistingClauses, Clause))
- return nullptr;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // 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");
+ assert(Clause.getNumIntExprs() < 2 &&
+ "Invalid number of expressions for Async");
+ return OpenACCAsyncClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
+ Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,
+ Clause.getEndLoc());
+}
- return OpenACCAsyncClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,
- Clause.getEndLoc());
- }
- case OpenACCClauseKind::Private: {
- // Restrictions only properly implemented on 'compute' and 'loop'
- // constructs, and 'compute'/'loop' constructs are the only construct that
- // can do anything with this yet, so skip/treat as unimplemented in this
- // case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
- Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
- break;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' and 'loop'
+ // constructs, and 'compute'/'loop' constructs are the only construct that
+ // can do anything with this yet, so skip/treat as unimplemented in this
+ // case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
+ Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
+ return isNotImplemented();
+
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getLParenLoc(),
+ Clause.getVarList(), Clause.getEndLoc());
+}
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
+OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCFirstPrivateClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
+ Clause.getEndLoc());
+}
- return OpenACCPrivateClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
- }
- case OpenACCClauseKind::FirstPrivate: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCNoCreateClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getLParenLoc(),
+ Clause.getVarList(), Clause.getEndLoc());
+}
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
+OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCPresentClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getLParenLoc(),
+ Clause.getVarList(), Clause.getEndLoc());
+}
- return OpenACCFirstPrivateClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
- }
- case OpenACCClauseKind::NoCreate: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCCopyClause::Create(
+ Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
+ Clause.getVarList(), Clause.getEndLoc());
+}
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
+OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCCopyInClause::Create(
+ Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
+ Clause.isReadOnly(), Clause.getVarList(), Clause.getEndLoc());
+}
- return OpenACCNoCreateClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
- }
- case OpenACCClauseKind::Present: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCCopyOutClause::Create(
+ Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
+ Clause.isZero(), Clause.getVarList(), Clause.getEndLoc());
+}
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
+OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+ // ActOnVar ensured that everything is a valid variable reference, so there
+ // really isn't anything to do here. GCC does some duplicate-finding, though
+ // it isn't apparent in the standard where this is justified.
+
+ return OpenACCCreateClause::Create(
+ Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
+ Clause.isZero(), Clause.getVarList(), Clause.getEndLoc());
+}
- return OpenACCPresentClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
- }
- case OpenACCClauseKind::PresentOrCopy:
- case OpenACCClauseKind::PCopy:
- Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
- << Clause.getClauseKind() << OpenACCClauseKind::Copy;
- LLVM_FALLTHROUGH;
- case OpenACCClauseKind::Copy: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // ActOnVar ensured that everything is a valid variable reference, but we
+ // still have to make sure it is a pointer type.
+ llvm::SmallVector<Expr *> VarList{Clause.getVarList().begin(),
+ Clause.getVarList().end()};
+ VarList.erase(std::remove_if(VarList.begin(), VarList.end(),
+ [&](Expr *E) {
+ return SemaRef.CheckVarIsPointerType(
+ OpenACCClauseKind::Attach, E);
+ }),
+ VarList.end());
+ Clause.setVarListDetails(VarList,
+ /*IsReadOnly=*/false, /*IsZero=*/false);
+ return OpenACCAttachClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getLParenLoc(), Clause.getVarList(),
+ Clause.getEndLoc());
+}
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
+OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // ActOnVar ensured that everything is a valid variable reference, but we
+ // still have to make sure it is a pointer type.
+ llvm::SmallVector<Expr *> VarList{Clause.getVarList().begin(),
+ Clause.getVarList().end()};
+ VarList.erase(std::remove_if(VarList.begin(), VarList.end(),
+ [&](Expr *E) {
+ return SemaRef.CheckVarIsPointerType(
+ OpenACCClauseKind::DevicePtr, E);
+ }),
+ VarList.end());
+ Clause.setVarListDetails(VarList,
+ /*IsReadOnly=*/false, /*IsZero=*/false);
+
+ return OpenACCDevicePtrClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
+ Clause.getEndLoc());
+}
- return OpenACCCopyClause::Create(
- getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(),
- Clause.getLParenLoc(), Clause.getVarList(), Clause.getEndLoc());
- }
- case OpenACCClauseKind::PresentOrCopyIn:
- case OpenACCClauseKind::PCopyIn:
- Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
- << Clause.getClauseKind() << OpenACCClauseKind::CopyIn;
- LLVM_FALLTHROUGH;
- case OpenACCClauseKind::CopyIn: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ return OpenACCWaitClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getDevNumExpr(),
+ Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc());
+}
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
+OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' and 'loop'
+ // constructs, and 'compute'/'loop' constructs are the only construct that
+ // can do anything with this yet, so skip/treat as unimplemented in this
+ // case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
+ Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
+ return isNotImplemented();
+
+ // TODO OpenACC: Once we get enough of the CodeGen implemented that we have
+ // a source for the list of valid architectures, we need to warn on unknown
+ // identifiers here.
+
+ return OpenACCDeviceTypeClause::Create(
+ Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
+ Clause.getDeviceTypeArchitectures(), Clause.getEndLoc());
+}
- return OpenACCCopyInClause::Create(
- getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(),
- Clause.getLParenLoc(), Clause.isReadOnly(), Clause.getVarList(),
- Clause.getEndLoc());
+OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'loop' constructs, and it is
+ // the only construct that can do anything with this, so skip/treat as
+ // unimplemented for the combined constructs.
+ if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
+ return isNotImplemented();
+
+ // 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, 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;
}
- case OpenACCClauseKind::PresentOrCopyOut:
- case OpenACCClauseKind::PCopyOut:
- Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
- << Clause.getClauseKind() << OpenACCClauseKind::CopyOut;
- LLVM_FALLTHROUGH;
- case OpenACCClauseKind::CopyOut: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
+ return OpenACCAutoClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getEndLoc());
+}
- return OpenACCCopyOutClause::Create(
- getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(),
- Clause.getLParenLoc(), Clause.isZero(), Clause.getVarList(),
- Clause.getEndLoc());
+OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'loop' constructs, and it is
+ // the only construct that can do anything with this, so skip/treat as
+ // unimplemented for the combined constructs.
+ if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
+ return isNotImplemented();
+
+ // 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, 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;
}
- case OpenACCClauseKind::PresentOrCreate:
- case OpenACCClauseKind::PCreate:
- Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
- << Clause.getClauseKind() << OpenACCClauseKind::Create;
- LLVM_FALLTHROUGH;
- case OpenACCClauseKind::Create: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
-
- // ActOnVar ensured that everything is a valid variable reference, so there
- // really isn't anything to do here. GCC does some duplicate-finding, though
- // it isn't apparent in the standard where this is justified.
- return OpenACCCreateClause::Create(getASTContext(), Clause.getClauseKind(),
- Clause.getBeginLoc(),
- Clause.getLParenLoc(), Clause.isZero(),
- Clause.getVarList(), Clause.getEndLoc());
- }
- case OpenACCClauseKind::Attach: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+ return OpenACCIndependentClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getEndLoc());
+}
- // ActOnVar ensured that everything is a valid variable reference, but we
- // still have to make sure it is a pointer type.
- llvm::SmallVector<Expr *> VarList{Clause.getVarList().begin(),
- Clause.getVarList().end()};
- VarList.erase(std::remove_if(VarList.begin(), VarList.end(), [&](Expr *E) {
- return CheckVarIsPointerType(OpenACCClauseKind::Attach, E);
- }), VarList.end());
- Clause.setVarListDetails(VarList,
- /*IsReadOnly=*/false, /*IsZero=*/false);
-
- return OpenACCAttachClause::Create(getASTContext(), Clause.getBeginLoc(),
- Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
+OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'loop' constructs, and it is
+ // the only construct that can do anything with this, so skip/treat as
+ // unimplemented for the combined constructs.
+ if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
+ return isNotImplemented();
+
+ // 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>);
+ 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;
}
- case OpenACCClauseKind::DevicePtr: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
- // ActOnVar ensured that everything is a valid variable reference, but we
- // still have to make sure it is a pointer type.
- llvm::SmallVector<Expr *> VarList{Clause.getVarList().begin(),
- Clause.getVarList().end()};
- VarList.erase(std::remove_if(VarList.begin(), VarList.end(), [&](Expr *E) {
- return CheckVarIsPointerType(OpenACCClauseKind::DevicePtr, E);
- }), VarList.end());
- Clause.setVarListDetails(VarList,
- /*IsReadOnly=*/false, /*IsZero=*/false);
-
- return OpenACCDevicePtrClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
- }
- case OpenACCClauseKind::Wait: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
+ // OpenACC 3.3 2.9:
+ // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
+ // appears.
+ Itr = llvm::find_if(ExistingClauses,
+ llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
+ OpenACCVectorClause>);
- return OpenACCWaitClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getDevNumExpr(), Clause.getQueuesLoc(), Clause.getQueueIdExprs(),
- Clause.getEndLoc());
+ if (Itr != ExistingClauses.end()) {
+ SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
+ << Clause.getClauseKind() << (*Itr)->getClauseKind();
+ SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
+ return nullptr;
}
- case OpenACCClauseKind::DType:
- case OpenACCClauseKind::DeviceType: {
- // Restrictions only properly implemented on 'compute' and 'loop'
- // constructs, and 'compute'/'loop' constructs are the only construct that
- // can do anything with this yet, so skip/treat as unimplemented in this
- // case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
- Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
- break;
- // TODO OpenACC: Once we get enough of the CodeGen implemented that we have
- // a source for the list of valid architectures, we need to warn on unknown
- // identifiers here.
-
- return OpenACCDeviceTypeClause::Create(
- getASTContext(), Clause.getClauseKind(), Clause.getBeginLoc(),
- Clause.getLParenLoc(), Clause.getDeviceTypeArchitectures(),
- Clause.getEndLoc());
- }
- case OpenACCClauseKind::Auto: {
- // Restrictions only properly implemented on 'loop' constructs, and it is
- // the only construct that can do anything with this, so skip/treat as
- // unimplemented for the combined constructs.
- if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
- break;
+ // TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some
+ // restrictions when there is a 'seq' clause in place. We probably need to
+ // implement that.
+ return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),
+ Clause.getEndLoc());
+}
- // 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, OpenACCSeqClause>);
- if (Itr != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
- << Clause.getClauseKind() << Clause.getDirectiveKind();
- Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
+OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
+ SemaOpenACC::OpenACCParsedClause &Clause) {
+ // Restrictions only properly implemented on 'compute' constructs, and
+ // 'compute' constructs are the only construct that can do anything with
+ // this yet, so skip/treat as unimplemented in this case.
+ if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
+ return isNotImplemented();
+
+ // OpenACC 3.3 Section 2.5.4:
+ // A reduction clause may not appear on a parallel construct with a
+ // num_gangs clause that has more than one argument.
+ if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel) {
+ auto NumGangsClauses = llvm::make_filter_range(
+ ExistingClauses, llvm::IsaPred<OpenACCNumGangsClause>);
+
+ for (auto *NGC : NumGangsClauses) {
+ unsigned NumExprs =
+ cast<OpenACCNumGangsClause>(NGC)->getIntExprs().size();
+
+ if (NumExprs > 1) {
+ SemaRef.Diag(Clause.getBeginLoc(),
+ diag::err_acc_reduction_num_gangs_conflict)
+ << NumExprs;
+ SemaRef.Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here);
+ return nullptr;
+ }
}
-
- return OpenACCAutoClause::Create(getASTContext(), Clause.getBeginLoc(),
- Clause.getEndLoc());
}
- case OpenACCClauseKind::Independent: {
- // Restrictions only properly implemented on 'loop' constructs, and it is
- // the only construct that can do anything with this, so skip/treat as
- // unimplemented for the combined constructs.
- if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
- break;
- // 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, OpenACCSeqClause>);
- if (Itr != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
- << Clause.getClauseKind() << Clause.getDirectiveKind();
- Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- }
+ SmallVector<Expr *> ValidVars;
+
+ for (Expr *Var : Clause.getVarList()) {
+ ExprResult Res = SemaRef.CheckReductionVar(Var);
- return OpenACCIndependentClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getEndLoc());
+ if (Res.isUsable())
+ ValidVars.push_back(Res.get());
}
- case OpenACCClauseKind::Seq: {
- // Restrictions only properly implemented on 'loop' constructs, and it is
- // the only construct that can do anything with this, so skip/treat as
- // unimplemented for the combined constructs.
- if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
- break;
- // 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>);
- if (Itr != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
- << Clause.getClauseKind() << Clause.getDirectiveKind();
- Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- }
+ return OpenACCReductionClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getReductionOp(),
+ ValidVars, Clause.getEndLoc());
+}
- // OpenACC 3.3 2.9:
- // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
- // appears.
- Itr = llvm::find_if(ExistingClauses,
- llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
- OpenACCVectorClause>);
+} // namespace
- if (Itr != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
- << Clause.getClauseKind() << (*Itr)->getClauseKind();
- Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- }
+SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
- // TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some
- // restrictions when there is a 'seq' clause in place. We probably need to
- // implement that.
- return OpenACCSeqClause::Create(getASTContext(), Clause.getBeginLoc(),
- Clause.getEndLoc());
+SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(SemaOpenACC &S,
+ OpenACCDirectiveKind DK)
+ : SemaRef(S), WasInsideComputeConstruct(S.InsideComputeConstruct),
+ DirKind(DK) {
+ // Compute constructs end up taking their 'loop'.
+ if (DirKind == OpenACCDirectiveKind::Parallel ||
+ DirKind == OpenACCDirectiveKind::Serial ||
+ DirKind == OpenACCDirectiveKind::Kernels) {
+ SemaRef.InsideComputeConstruct = true;
+ SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);
}
- case OpenACCClauseKind::Gang:
- case OpenACCClauseKind::Worker:
- case OpenACCClauseKind::Vector: {
- // OpenACC 3.3 2.9:
- // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
- // appears.
- const auto *Itr =
- llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
+}
- if (Itr != ExistingClauses.end()) {
- Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
- << Clause.getClauseKind() << (*Itr)->getClauseKind();
- Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
- }
- // Not yet implemented, so immediately drop to the 'not yet implemented'
- // diagnostic.
- break;
+SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
+ SemaRef.InsideComputeConstruct = WasInsideComputeConstruct;
+ if (DirKind == OpenACCDirectiveKind::Parallel ||
+ DirKind == OpenACCDirectiveKind::Serial ||
+ DirKind == OpenACCDirectiveKind::Kernels) {
+ assert(SemaRef.ParentlessLoopConstructs.empty() &&
+ "Didn't consume loop construct list?");
+ SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);
}
- case OpenACCClauseKind::Reduction: {
- // Restrictions only properly implemented on 'compute' constructs, and
- // 'compute' constructs are the only construct that can do anything with
- // this yet, so skip/treat as unimplemented in this case.
- if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
- break;
-
- // OpenACC 3.3 Section 2.5.4:
- // A reduction clause may not appear on a parallel construct with a
- // num_gangs clause that has more than one argument.
- if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel) {
- auto NumGangsClauses = llvm::make_filter_range(
- ExistingClauses, llvm::IsaPred<OpenACCNumGangsClause>);
-
- for (auto *NGC : NumGangsClauses) {
- unsigned NumExprs =
- cast<OpenACCNumGangsClause>(NGC)->getIntExprs().size();
-
- if (NumExprs > 1) {
- Diag(Clause.getBeginLoc(), diag::err_acc_reduction_num_gangs_conflict)
- << NumExprs;
- Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here);
- return nullptr;
- }
- }
- }
-
- SmallVector<Expr *> ValidVars;
-
- for (Expr *Var : Clause.getVarList()) {
- ExprResult Res = CheckReductionVar(Var);
+}
- if (Res.isUsable())
- ValidVars.push_back(Res.get());
- }
+OpenACCClause *
+SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
+ OpenACCParsedClause &Clause) {
+ if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
+ return nullptr;
- return OpenACCReductionClause::Create(
- getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
- Clause.getReductionOp(), ValidVars, Clause.getEndLoc());
+ // 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;
}
- default:
- break;
+
+ if (const auto *DevTypeClause =
+ llvm::find_if(ExistingClauses,
+ [&](const OpenACCClause *C) {
+ return isa<OpenACCDeviceTypeClause>(C);
+ });
+ DevTypeClause != ExistingClauses.end()) {
+ if (checkValidAfterDeviceType(
+ *this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
+ return nullptr;
}
- Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
- << Clause.getClauseKind();
- return nullptr;
+ SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses};
+ OpenACCClause *Result = Visitor.Visit(Clause);
+ assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&
+ "Created wrong clause?");
+
+ if (Visitor.diagNotImplemented())
+ Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
+ << Clause.getClauseKind();
+
+ return Result;
+
+ // switch (Clause.getClauseKind()) {
+ // case OpenACCClauseKind::PresentOrCopy:
+ // case OpenACCClauseKind::PCopy:
+ // Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
+ // << Clause.getClauseKind() << OpenACCClauseKind::Copy;
+ // LLVM_FALLTHROUGH;
+ // case OpenACCClauseKind::PresentOrCreate:
+ // case OpenACCClauseKind::PCreate:
+ // Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
+ // << Clause.getClauseKind() << OpenACCClauseKind::Create;
+ // LLVM_FALLTHROUGH;
+ //
+ //
+ //
+ //
+ // case OpenACCClauseKind::DType:
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ // case OpenACCClauseKind::Gang:
+ // case OpenACCClauseKind::Worker:
+ // case OpenACCClauseKind::Vector: {
+ // // OpenACC 3.3 2.9:
+ // // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq'
+ // clause
+ // // appears.
+ // const auto *Itr =
+ // llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
+ //
+ // if (Itr != ExistingClauses.end()) {
+ // Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
+ // << Clause.getClauseKind() << (*Itr)->getClauseKind();
+ // Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
+ // }
+ // // Not yet implemented, so immediately drop to the 'not yet implemented'
+ // // diagnostic.
+ // break;
+ // }
+ // */
+
}
/// OpenACC 3.3 section 2.5.15:
More information about the cfe-commits
mailing list