diff --git a/flang/lib/Semantics/check-acc-structure.h b/flang/lib/Semantics/check-acc-structure.h --- a/flang/lib/Semantics/check-acc-structure.h +++ b/flang/lib/Semantics/check-acc-structure.h @@ -66,50 +66,8 @@ void Leave(const parser::AccClauseList &); void Enter(const parser::AccClause &); - void Enter(const parser::AccClause::Auto &); - void Enter(const parser::AccClause::Async &); - void Enter(const parser::AccClause::Attach &); - void Enter(const parser::AccClause::Bind &); - void Enter(const parser::AccClause::Capture &); - void Enter(const parser::AccClause::Create &); - void Enter(const parser::AccClause::Collapse &); - void Enter(const parser::AccClause::Copy &); - void Enter(const parser::AccClause::Copyin &); - void Enter(const parser::AccClause::Copyout &); - void Enter(const parser::AccClause::Default &); - void Enter(const parser::AccClause::DefaultAsync &); - void Enter(const parser::AccClause::Delete &); - void Enter(const parser::AccClause::Detach &); - void Enter(const parser::AccClause::Device &); - void Enter(const parser::AccClause::DeviceNum &); - void Enter(const parser::AccClause::Deviceptr &); - void Enter(const parser::AccClause::DeviceResident &); - void Enter(const parser::AccClause::DeviceType &); - void Enter(const parser::AccClause::Finalize &); - void Enter(const parser::AccClause::Firstprivate &); - void Enter(const parser::AccClause::Gang &); - void Enter(const parser::AccClause::Host &); - void Enter(const parser::AccClause::If &); - void Enter(const parser::AccClause::IfPresent &); - void Enter(const parser::AccClause::Independent &); - void Enter(const parser::AccClause::Link &); - void Enter(const parser::AccClause::NoCreate &); - void Enter(const parser::AccClause::Nohost &); - void Enter(const parser::AccClause::NumGangs &); - void Enter(const parser::AccClause::NumWorkers &); - void Enter(const parser::AccClause::Present &); - void Enter(const parser::AccClause::Private &); - void Enter(const parser::AccClause::Read &); - void Enter(const parser::AccClause::Reduction &); - void Enter(const parser::AccClause::Self &); - void Enter(const parser::AccClause::Seq &); - void Enter(const parser::AccClause::Tile &); - void Enter(const parser::AccClause::UseDevice &); - void Enter(const parser::AccClause::Vector &); - void Enter(const parser::AccClause::VectorLength &); - void Enter(const parser::AccClause::Wait &); - void Enter(const parser::AccClause::Worker &); - void Enter(const parser::AccClause::Write &); +#define GEN_FLANG_CLAUSE_CHECK_ENTER +#include "llvm/Frontend/OpenACC/ACC.inc" private: diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp --- a/flang/lib/Semantics/check-acc-structure.cpp +++ b/flang/lib/Semantics/check-acc-structure.cpp @@ -344,6 +344,7 @@ CHECK_SIMPLE_CLAUSE(Wait, ACCC_wait) CHECK_SIMPLE_CLAUSE(Worker, ACCC_worker) CHECK_SIMPLE_CLAUSE(Write, ACCC_write) +CHECK_SIMPLE_CLAUSE(Unknown, ACCC_unknown) void AccStructureChecker::Enter(const parser::AccClause::Create &c) { CheckAllowed(llvm::acc::Clause::ACCC_create); diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -127,50 +127,9 @@ void Leave(const parser::OmpClauseList &); void Enter(const parser::OmpClause &); - void Enter(const parser::OmpClause::Allocate &); - void Enter(const parser::OmpClause::Allocator &); - void Enter(const parser::OmpClause::Inbranch &); - void Enter(const parser::OmpClause::Mergeable &); - void Enter(const parser::OmpClause::Nogroup &); - void Enter(const parser::OmpClause::Nowait &); - void Enter(const parser::OmpClause::Notinbranch &); - void Enter(const parser::OmpClause::Untied &); - void Enter(const parser::OmpClause::Collapse &); - void Enter(const parser::OmpClause::Copyin &); - void Enter(const parser::OmpClause::Copyprivate &); - void Enter(const parser::OmpClause::Default &); - void Enter(const parser::OmpClause::Device &); - void Enter(const parser::OmpClause::DistSchedule &); - void Enter(const parser::OmpClause::Final &); - void Enter(const parser::OmpClause::Firstprivate &); - void Enter(const parser::OmpClause::From &); - void Enter(const parser::OmpClause::Grainsize &); - void Enter(const parser::OmpClause::Lastprivate &); - void Enter(const parser::OmpClause::NumTasks &); - void Enter(const parser::OmpClause::NumTeams &); - void Enter(const parser::OmpClause::NumThreads &); - void Enter(const parser::OmpClause::Ordered &); - void Enter(const parser::OmpClause::Priority &); - void Enter(const parser::OmpClause::Private &); - void Enter(const parser::OmpClause::ProcBind &); - void Enter(const parser::OmpClause::Reduction &); - void Enter(const parser::OmpClause::Safelen &); - void Enter(const parser::OmpClause::Shared &); - void Enter(const parser::OmpClause::Simdlen &); - void Enter(const parser::OmpClause::TaskReduction &); - void Enter(const parser::OmpClause::ThreadLimit &); - void Enter(const parser::OmpClause::To &); - void Enter(const parser::OmpClause::Link &); - void Enter(const parser::OmpClause::Uniform &); - void Enter(const parser::OmpClause::UseDevicePtr &); - void Enter(const parser::OmpClause::IsDevicePtr &); - // Memory-order-clause - void Enter(const parser::OmpClause::SeqCst &); - void Enter(const parser::OmpClause::AcqRel &); - void Enter(const parser::OmpClause::Release &); - void Enter(const parser::OmpClause::Acquire &); - void Enter(const parser::OmpClause::Relaxed &); - void Enter(const parser::OmpClause::Hint &); + +#define GEN_FLANG_CLAUSE_CHECK_ENTER +#include "llvm/Frontend/OpenMP/OMP.inc" void Enter(const parser::OmpAtomicRead &); void Leave(const parser::OmpAtomicRead &); @@ -180,13 +139,6 @@ void Leave(const parser::OmpAtomicUpdate &); void Enter(const parser::OmpAtomicCapture &); void Leave(const parser::OmpAtomic &); - void Enter(const parser::OmpAlignedClause &); - void Enter(const parser::OmpDefaultmapClause &); - void Enter(const parser::OmpDependClause &); - void Enter(const parser::OmpIfClause &); - void Enter(const parser::OmpLinearClause &); - void Enter(const parser::OmpMapClause &); - void Enter(const parser::OmpScheduleClause &); private: bool HasInvalidWorksharingNesting( diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -473,14 +473,36 @@ } // Following clauses do not have a seperate node in parse-tree.h. -// They fall under 'struct OmpClause' in parse-tree.h. +CHECK_SIMPLE_CLAUSE(AcqRel, OMPC_acq_rel) +CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire) +CHECK_SIMPLE_CLAUSE(AtomicDefaultMemOrder, OMPC_atomic_default_mem_order) +CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity) CHECK_SIMPLE_CLAUSE(Allocate, OMPC_allocate) +CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture) CHECK_SIMPLE_CLAUSE(Copyin, OMPC_copyin) CHECK_SIMPLE_CLAUSE(Copyprivate, OMPC_copyprivate) CHECK_SIMPLE_CLAUSE(Default, OMPC_default) +CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj) +CHECK_SIMPLE_CLAUSE(Destroy, OMPC_destroy) +CHECK_SIMPLE_CLAUSE(Detach, OMPC_detach) CHECK_SIMPLE_CLAUSE(Device, OMPC_device) +CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type) +CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) +CHECK_SIMPLE_CLAUSE(DynamicAllocators, OMPC_dynamic_allocators) +CHECK_SIMPLE_CLAUSE(Exclusive, OMPC_exclusive) CHECK_SIMPLE_CLAUSE(Final, OMPC_final) +CHECK_SIMPLE_CLAUSE(Flush, OMPC_flush) CHECK_SIMPLE_CLAUSE(From, OMPC_from) +CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint) +CHECK_SIMPLE_CLAUSE(InReduction, OMPC_in_reduction) +CHECK_SIMPLE_CLAUSE(Inclusive, OMPC_inclusive) +CHECK_SIMPLE_CLAUSE(Match, OMPC_match) +CHECK_SIMPLE_CLAUSE(Nontemporal, OMPC_nontemporal) +CHECK_SIMPLE_CLAUSE(Order, OMPC_order) +CHECK_SIMPLE_CLAUSE(Read, OMPC_read) +CHECK_SIMPLE_CLAUSE(ReverseOffload, OMPC_reverse_offload) +CHECK_SIMPLE_CLAUSE(Threadprivate, OMPC_threadprivate) +CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads) CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch) CHECK_SIMPLE_CLAUSE(IsDevicePtr, OMPC_is_device_ptr) CHECK_SIMPLE_CLAUSE(Lastprivate, OMPC_lastprivate) @@ -489,20 +511,24 @@ CHECK_SIMPLE_CLAUSE(Nogroup, OMPC_nogroup) CHECK_SIMPLE_CLAUSE(Notinbranch, OMPC_notinbranch) CHECK_SIMPLE_CLAUSE(Nowait, OMPC_nowait) +CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind) CHECK_SIMPLE_CLAUSE(Reduction, OMPC_reduction) +CHECK_SIMPLE_CLAUSE(Release, OMPC_release) +CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed) +CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst) +CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd) CHECK_SIMPLE_CLAUSE(TaskReduction, OMPC_task_reduction) CHECK_SIMPLE_CLAUSE(To, OMPC_to) +CHECK_SIMPLE_CLAUSE(UnifiedAddress, OMPC_unified_address) +CHECK_SIMPLE_CLAUSE(UnifiedSharedMemory, OMPC_unified_shared_memory) CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform) +CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown) CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied) CHECK_SIMPLE_CLAUSE(UseDevicePtr, OMPC_use_device_ptr) -CHECK_SIMPLE_CLAUSE(AcqRel, OMPC_acq_rel) -CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire) -CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst) -CHECK_SIMPLE_CLAUSE(Release, OMPC_release) -CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed) -CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint) -CHECK_SIMPLE_CLAUSE(ProcBind, OMPC_proc_bind) -CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) +CHECK_SIMPLE_CLAUSE(UsesAllocators, OMPC_uses_allocators) +CHECK_SIMPLE_CLAUSE(Update, OMPC_update) +CHECK_SIMPLE_CLAUSE(UseDeviceAddr, OMPC_use_device_addr) +CHECK_SIMPLE_CLAUSE(Write, OMPC_write) CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator) CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize) @@ -615,27 +641,26 @@ } // Restrictions specific to each clause are implemented apart from the // generalized restrictions. -void OmpStructureChecker::Enter(const parser::OmpAlignedClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) { CheckAllowed(llvm::omp::Clause::OMPC_aligned); if (const auto &expr{ - std::get>(x.t)}) { + std::get>(x.v.t)}) { RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_aligned, *expr); } // 2.8.1 TODO: list-item attribute check } -void OmpStructureChecker::Enter(const parser::OmpDefaultmapClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) { CheckAllowed(llvm::omp::Clause::OMPC_defaultmap); using VariableCategory = parser::OmpDefaultmapClause::VariableCategory; - if (!std::get>(x.t)) { + if (!std::get>(x.v.t)) { context_.Say(GetContext().clauseSource, "The argument TOFROM:SCALAR must be specified on the DEFAULTMAP " "clause"_err_en_US); } } -void OmpStructureChecker::Enter(const parser::OmpIfClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::If &x) { CheckAllowed(llvm::omp::Clause::OMPC_if); - using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier; static std::unordered_map dirNameModifierMap{{dirNameModifier::Parallel, llvm::omp::parallelSet}, @@ -651,7 +676,7 @@ {dirNameModifier::Task, {llvm::omp::Directive::OMPD_task}}, {dirNameModifier::Taskloop, llvm::omp::taskloopSet}}; if (const auto &directiveName{ - std::get>(x.t)}) { + std::get>(x.v.t)}) { auto search{dirNameModifierMap.find(*directiveName)}; if (search == dirNameModifierMap.end() || !search->second.test(GetContext().directive)) { @@ -666,12 +691,12 @@ } } -void OmpStructureChecker::Enter(const parser::OmpLinearClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) { CheckAllowed(llvm::omp::Clause::OMPC_linear); // 2.7 Loop Construct Restriction if ((llvm::omp::doSet | llvm::omp::simdSet).test(GetContext().directive)) { - if (std::holds_alternative(x.u)) { + if (std::holds_alternative(x.v.u)) { context_.Say(GetContext().clauseSource, "A modifier may not be specified in a LINEAR clause " "on the %s directive"_err_en_US, @@ -701,9 +726,10 @@ } } -void OmpStructureChecker::Enter(const parser::OmpMapClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) { CheckAllowed(llvm::omp::Clause::OMPC_map); - if (const auto &maptype{std::get>(x.t)}) { + + if (const auto &maptype{std::get>(x.v.t)}) { using Type = parser::OmpMapType::Type; const Type &type{std::get(maptype->t)}; switch (GetContext().directive) { @@ -746,13 +772,14 @@ } return false; } -void OmpStructureChecker::Enter(const parser::OmpScheduleClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) { CheckAllowed(llvm::omp::Clause::OMPC_schedule); + const parser::OmpScheduleClause &scheduleClause = x.v; // 2.7 Loop Construct Restriction if (llvm::omp::doSet.test(GetContext().directive)) { - const auto &kind{std::get<1>(x.t)}; - const auto &chunk{std::get<2>(x.t)}; + const auto &kind{std::get<1>(scheduleClause.t)}; + const auto &chunk{std::get<2>(scheduleClause.t)}; if (chunk) { if (kind == parser::OmpScheduleClause::ScheduleType::Runtime || kind == parser::OmpScheduleClause::ScheduleType::Auto) { @@ -762,15 +789,15 @@ parser::ToUpperCaseLetters( parser::OmpScheduleClause::EnumToString(kind))); } - if (const auto &chunkExpr{ - std::get>(x.t)}) { + if (const auto &chunkExpr{std::get>( + scheduleClause.t)}) { RequiresPositiveParameter( llvm::omp::Clause::OMPC_schedule, *chunkExpr, "chunk size"); } } - if (ScheduleModifierHasType( - x, parser::OmpScheduleModifierType::ModType::Nonmonotonic)) { + if (ScheduleModifierHasType(scheduleClause, + parser::OmpScheduleModifierType::ModType::Nonmonotonic)) { if (kind != parser::OmpScheduleClause::ScheduleType::Dynamic && kind != parser::OmpScheduleClause::ScheduleType::Guided) { context_.Say(GetContext().clauseSource, @@ -781,9 +808,9 @@ } } -void OmpStructureChecker::Enter(const parser::OmpDependClause &x) { +void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) { CheckAllowed(llvm::omp::Clause::OMPC_depend); - if (const auto *inOut{std::get_if(&x.u)}) { + if (const auto *inOut{std::get_if(&x.v.u)}) { const auto &designators{std::get>(inOut->t)}; for (const auto &ele : designators) { if (const auto *dataRef{std::get_if(&ele.u)}) { diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp --- a/llvm/utils/TableGen/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/DirectiveEmitter.cpp @@ -633,6 +633,20 @@ } } +// Generate check Enter functions for clauses classes. +void GenerateFlangClauseCheckEnter(const DirectiveLanguage &DirLang, + raw_ostream &OS) { + + IfDefScope Scope("GEN_FLANG_CLAUSE_CHECK_ENTER", OS); + + OS << "\n"; + for (const auto &C : DirLang.getClauses()) { + Clause Clause{C}; + OS << "void Enter(const parser::" << DirLang.getFlangClauseBaseClass() + << "::" << Clause.getFormattedParserClassName() << " &);\n"; + } +} + // Generate the implementation section for the enumeration in the directive // language void EmitDirectivesFlangImpl(const DirectiveLanguage &DirLang, @@ -649,6 +663,8 @@ GenerateFlangClauseDump(DirLang, OS); GenerateFlangClauseUnparse(DirLang, OS); + + GenerateFlangClauseCheckEnter(DirLang, OS); } void GenerateClauseClassMacro(const DirectiveLanguage &DirLang,