[flang-commits] [flang] c988e78 - [flang][openacc] Enforce restriction on declare directive
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Wed Aug 2 21:27:06 PDT 2023
Author: Valentin Clement
Date: 2023-08-02T21:27:00-07:00
New Revision: c988e78f8e5e4777a872142885723d5f925f93b8
URL: https://github.com/llvm/llvm-project/commit/c988e78f8e5e4777a872142885723d5f925f93b8
DIFF: https://github.com/llvm/llvm-project/commit/c988e78f8e5e4777a872142885723d5f925f93b8.diff
LOG: [flang][openacc] Enforce restriction on declare directive
Enforce the following restriction specified in 2.13
A var may appear at most once in all the clauses of declare directives for a
function, subroutine, program, or module.
Reviewed By: razvanlupusoru
Differential Revision: https://reviews.llvm.org/D156945
Added:
Modified:
flang/lib/Semantics/check-acc-structure.cpp
flang/lib/Semantics/check-acc-structure.h
flang/lib/Semantics/semantics.cpp
flang/test/Semantics/OpenACC/acc-declare-validity.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp
index ff2fce261cd460..e8d55aa9bdd2e4 100644
--- a/flang/lib/Semantics/check-acc-structure.cpp
+++ b/flang/lib/Semantics/check-acc-structure.cpp
@@ -342,15 +342,12 @@ CHECK_SIMPLE_CLAUSE(Async, ACCC_async)
CHECK_SIMPLE_CLAUSE(Attach, ACCC_attach)
CHECK_SIMPLE_CLAUSE(Bind, ACCC_bind)
CHECK_SIMPLE_CLAUSE(Capture, ACCC_capture)
-CHECK_SIMPLE_CLAUSE(Copy, ACCC_copy)
CHECK_SIMPLE_CLAUSE(Default, ACCC_default)
CHECK_SIMPLE_CLAUSE(DefaultAsync, ACCC_default_async)
CHECK_SIMPLE_CLAUSE(Delete, ACCC_delete)
CHECK_SIMPLE_CLAUSE(Detach, ACCC_detach)
CHECK_SIMPLE_CLAUSE(Device, ACCC_device)
CHECK_SIMPLE_CLAUSE(DeviceNum, ACCC_device_num)
-CHECK_SIMPLE_CLAUSE(Deviceptr, ACCC_deviceptr)
-CHECK_SIMPLE_CLAUSE(DeviceResident, ACCC_device_resident)
CHECK_SIMPLE_CLAUSE(DeviceType, ACCC_device_type)
CHECK_SIMPLE_CLAUSE(Finalize, ACCC_finalize)
CHECK_SIMPLE_CLAUSE(Firstprivate, ACCC_firstprivate)
@@ -358,11 +355,9 @@ CHECK_SIMPLE_CLAUSE(Host, ACCC_host)
CHECK_SIMPLE_CLAUSE(If, ACCC_if)
CHECK_SIMPLE_CLAUSE(IfPresent, ACCC_if_present)
CHECK_SIMPLE_CLAUSE(Independent, ACCC_independent)
-CHECK_SIMPLE_CLAUSE(Link, ACCC_link)
CHECK_SIMPLE_CLAUSE(NoCreate, ACCC_no_create)
CHECK_SIMPLE_CLAUSE(Nohost, ACCC_nohost)
CHECK_SIMPLE_CLAUSE(NumWorkers, ACCC_num_workers)
-CHECK_SIMPLE_CLAUSE(Present, ACCC_present)
CHECK_SIMPLE_CLAUSE(Private, ACCC_private)
CHECK_SIMPLE_CLAUSE(Read, ACCC_read)
CHECK_SIMPLE_CLAUSE(Seq, ACCC_seq)
@@ -375,6 +370,39 @@ CHECK_SIMPLE_CLAUSE(Worker, ACCC_worker)
CHECK_SIMPLE_CLAUSE(Write, ACCC_write)
CHECK_SIMPLE_CLAUSE(Unknown, ACCC_unknown)
+void AccStructureChecker::CheckMultipleOccurrenceInDeclare(
+ const parser::AccObjectList &list, llvm::acc::Clause clause) {
+ if (GetContext().directive != llvm::acc::Directive::ACCD_declare)
+ return;
+ for (const auto &object : list.v) {
+ std::visit(
+ Fortran::common::visitors{
+ [&](const Fortran::parser::Designator &designator) {
+ if (const auto *name = getDesignatorNameIfDataRef(designator)) {
+ if (declareSymbols.contains(&name->symbol->GetUltimate())) {
+ context_.Say(GetContext().clauseSource,
+ "'%s' in the %s clause is already present in another "
+ "clause in this module"_err_en_US,
+ name->symbol->name(),
+ parser::ToUpperCaseLetters(
+ llvm::acc::getOpenACCClauseName(clause).str()));
+ }
+ declareSymbols.insert(&name->symbol->GetUltimate());
+ }
+ },
+ [&](const Fortran::parser::Name &name) {
+ // TODO: check common block
+ }},
+ object.u);
+ }
+}
+
+void AccStructureChecker::CheckMultipleOccurrenceInDeclare(
+ const parser::AccObjectListWithModifier &list, llvm::acc::Clause clause) {
+ const auto &objectList = std::get<Fortran::parser::AccObjectList>(list.t);
+ CheckMultipleOccurrenceInDeclare(objectList, clause);
+}
+
void AccStructureChecker::Enter(const parser::AccClause::Create &c) {
CheckAllowed(llvm::acc::Clause::ACCC_create);
const auto &modifierClause{c.v};
@@ -399,6 +427,8 @@ void AccStructureChecker::Enter(const parser::AccClause::Create &c) {
ContextDirectiveAsFortran());
}
}
+ CheckMultipleOccurrenceInDeclare(
+ modifierClause, llvm::acc::Clause::ACCC_create);
}
void AccStructureChecker::Enter(const parser::AccClause::Copyin &c) {
@@ -419,6 +449,8 @@ void AccStructureChecker::Enter(const parser::AccClause::Copyin &c) {
ContextDirectiveAsFortran());
}
}
+ CheckMultipleOccurrenceInDeclare(
+ modifierClause, llvm::acc::Clause::ACCC_copyin);
}
void AccStructureChecker::Enter(const parser::AccClause::Copyout &c) {
@@ -448,6 +480,8 @@ void AccStructureChecker::Enter(const parser::AccClause::Copyout &c) {
ContextDirectiveAsFortran());
}
}
+ CheckMultipleOccurrenceInDeclare(
+ modifierClause, llvm::acc::Clause::ACCC_copyout);
}
void AccStructureChecker::Enter(const parser::AccClause::Gang &g) {
@@ -563,8 +597,46 @@ void AccStructureChecker::Enter(const parser::AccClause::Collapse &x) {
llvm::acc::Clause::ACCC_collapse, collapseValue);
}
-llvm::StringRef AccStructureChecker::getClauseName(llvm::acc::Clause clause) {
- return llvm::acc::getOpenACCClauseName(clause);
+void AccStructureChecker::Enter(const parser::AccClause::Present &x) {
+ CheckAllowed(llvm::acc::Clause::ACCC_present);
+ CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_present);
+}
+
+void AccStructureChecker::Enter(const parser::AccClause::Copy &x) {
+ CheckAllowed(llvm::acc::Clause::ACCC_copy);
+ CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_copy);
+}
+
+void AccStructureChecker::Enter(const parser::AccClause::Deviceptr &x) {
+ CheckAllowed(llvm::acc::Clause::ACCC_deviceptr);
+ CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_deviceptr);
+}
+
+void AccStructureChecker::Enter(const parser::AccClause::DeviceResident &x) {
+ CheckAllowed(llvm::acc::Clause::ACCC_device_resident);
+ CheckMultipleOccurrenceInDeclare(
+ x.v, llvm::acc::Clause::ACCC_device_resident);
+}
+
+void AccStructureChecker::Enter(const parser::AccClause::Link &x) {
+ CheckAllowed(llvm::acc::Clause::ACCC_link);
+ CheckMultipleOccurrenceInDeclare(x.v, llvm::acc::Clause::ACCC_link);
+}
+
+void AccStructureChecker::Enter(const parser::Module &) {
+ declareSymbols.clear();
+}
+
+void AccStructureChecker::Enter(const parser::FunctionSubprogram &x) {
+ declareSymbols.clear();
+}
+
+void AccStructureChecker::Enter(const parser::SubroutineSubprogram &) {
+ declareSymbols.clear();
+}
+
+void AccStructureChecker::Enter(const parser::SeparateModuleSubprogram &) {
+ declareSymbols.clear();
}
llvm::StringRef AccStructureChecker::getDirectiveName(
@@ -572,4 +644,8 @@ llvm::StringRef AccStructureChecker::getDirectiveName(
return llvm::acc::getOpenACCDirectiveName(directive);
}
+llvm::StringRef AccStructureChecker::getClauseName(llvm::acc::Clause clause) {
+ return llvm::acc::getOpenACCClauseName(clause);
+}
+
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/check-acc-structure.h b/flang/lib/Semantics/check-acc-structure.h
index 42745a6ca69a11..8c0d7150dd47b0 100644
--- a/flang/lib/Semantics/check-acc-structure.h
+++ b/flang/lib/Semantics/check-acc-structure.h
@@ -18,6 +18,7 @@
#include "flang/Common/enum-set.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/semantics.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Frontend/OpenACC/ACC.h.inc"
using AccDirectiveSet = Fortran::common::EnumSet<llvm::acc::Directive,
@@ -66,6 +67,11 @@ class AccStructureChecker
void Leave(const parser::AccClauseList &);
void Enter(const parser::AccClause &);
+ void Enter(const parser::Module &);
+ void Enter(const parser::SubroutineSubprogram &);
+ void Enter(const parser::FunctionSubprogram &);
+ void Enter(const parser::SeparateModuleSubprogram &);
+
#define GEN_FLANG_CLAUSE_CHECK_ENTER
#include "llvm/Frontend/OpenACC/ACC.inc"
@@ -74,8 +80,14 @@ class AccStructureChecker
bool IsComputeConstruct(llvm::acc::Directive directive) const;
bool IsInsideComputeConstruct() const;
void CheckNotInComputeConstruct();
+ void CheckMultipleOccurrenceInDeclare(
+ const parser::AccObjectList &, llvm::acc::Clause);
+ void CheckMultipleOccurrenceInDeclare(
+ const parser::AccObjectListWithModifier &, llvm::acc::Clause);
llvm::StringRef getClauseName(llvm::acc::Clause clause) override;
llvm::StringRef getDirectiveName(llvm::acc::Directive directive) override;
+
+ llvm::SmallDenseSet<Symbol *> declareSymbols;
};
} // namespace Fortran::semantics
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index 6a52d312953936..f2be4465083d69 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -166,8 +166,6 @@ using StatementSemanticsPass2 = SemanticsVisitor<AllocateChecker,
MiscChecker, NamelistChecker, NullifyChecker, PurityChecker,
ReturnStmtChecker, SelectRankConstructChecker, SelectTypeChecker,
StopChecker>;
-using StatementSemanticsPass3 =
- SemanticsVisitor<AccStructureChecker, OmpStructureChecker, CUDAChecker>;
static bool PerformStatementSemantics(
SemanticsContext &context, parser::Program &program) {
@@ -178,10 +176,14 @@ static bool PerformStatementSemantics(
StatementSemanticsPass1{context}.Walk(program);
StatementSemanticsPass2 pass2{context};
pass2.Walk(program);
- if (context.languageFeatures().IsEnabled(common::LanguageFeature::OpenACC) ||
- context.languageFeatures().IsEnabled(common::LanguageFeature::OpenMP) ||
- context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
- StatementSemanticsPass3{context}.Walk(program);
+ if (context.languageFeatures().IsEnabled(common::LanguageFeature::OpenACC)) {
+ SemanticsVisitor<AccStructureChecker>{context}.Walk(program);
+ }
+ if (context.languageFeatures().IsEnabled(common::LanguageFeature::OpenMP)) {
+ SemanticsVisitor<OmpStructureChecker>{context}.Walk(program);
+ }
+ if (context.languageFeatures().IsEnabled(common::LanguageFeature::CUDA)) {
+ SemanticsVisitor<CUDAChecker>{context}.Walk(program);
}
if (!context.AnyFatalError()) {
pass2.CompileDataInitializationsIntoInitializers();
diff --git a/flang/test/Semantics/OpenACC/acc-declare-validity.f90 b/flang/test/Semantics/OpenACC/acc-declare-validity.f90
index 6fa3b33bb2ccde..c0333d78dd9f78 100644
--- a/flang/test/Semantics/OpenACC/acc-declare-validity.f90
+++ b/flang/test/Semantics/OpenACC/acc-declare-validity.f90
@@ -7,31 +7,34 @@ module openacc_declare_validity
implicit none
- real(8), dimension(10) :: aa, bb, ab, cc
+ real(8), dimension(10) :: aa, bb, ab, ac, ad, ae, af, cc, dd
!ERROR: At least one clause is required on the DECLARE directive
!$acc declare
!$acc declare create(aa, bb)
+ !ERROR: 'aa' in the CREATE clause is already present in another clause in this module
+ !$acc declare create(aa)
+
!$acc declare link(ab)
!$acc declare device_resident(cc)
!ERROR: COPYOUT clause is not allowed on the DECLARE directive in module declaration section
- !$acc declare copyout(ab)
+ !$acc declare copyout(ac)
!ERROR: COPY clause is not allowed on the DECLARE directive in module declaration section
- !$acc declare copy(ab)
+ !$acc declare copy(af)
!ERROR: PRESENT clause is not allowed on the DECLARE directive in module declaration section
- !$acc declare present(ab)
+ !$acc declare present(ad)
!ERROR: DEVICEPTR clause is not allowed on the DECLARE directive in module declaration section
- !$acc declare deviceptr(ab)
+ !$acc declare deviceptr(ae)
!ERROR: The ZERO modifier is not allowed for the CREATE clause on the DECLARE directive
- !$acc declare create(zero: aa)
+ !$acc declare create(zero: dd)
contains
@@ -39,6 +42,8 @@ subroutine sub1(cc, dd)
real(8) :: cc(:)
real(8) :: dd(:)
!$acc declare present(cc, dd)
+ !ERROR: 'cc' in the CREATE clause is already present in another clause in this module
+ !$acc declare create(cc)
end subroutine sub1
function fct1(ee, ff, gg, hh, ii)
More information about the flang-commits
mailing list