[flang][directive] Enforce basic semantic check for all clauses

This patch is a follow up to D94821 to ensure the correct behavior of the
general directive structure checker.
This patch add the generation of the Enter function declaration for clauses in
the TableGen backend.
This helps to ensure each clauses declared in the TableGen file has at least
a basic check.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D95108

GitOrigin-RevId: 3f46c209f1527530ca8e60a51d08e32e886fa11b
diff --git a/lib/Semantics/check-acc-structure.cpp b/lib/Semantics/check-acc-structure.cpp
index 2f3138d..537b59d 100644
--- a/lib/Semantics/check-acc-structure.cpp
+++ b/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/lib/Semantics/check-acc-structure.h b/lib/Semantics/check-acc-structure.h
index ffe468c..d7de0c5 100644
--- a/lib/Semantics/check-acc-structure.h
+++ b/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/lib/Semantics/check-omp-structure.cpp b/lib/Semantics/check-omp-structure.cpp
index 16f851a..2803f2f 100644
--- a/lib/Semantics/check-omp-structure.cpp
+++ b/lib/Semantics/check-omp-structure.cpp
@@ -472,15 +472,37 @@
   SetContextClause(x);
 }
 
-// Following clauses do not have a seperate node in parse-tree.h.
-// They fall under 'struct OmpClause' in parse-tree.h.
+// Following clauses do not have a separate node 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(TaskReduction, OMPC_task_reduction)
-CHECK_SIMPLE_CLAUSE(To, OMPC_to)
-CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform)
-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(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(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<std::optional<parser::ScalarIntConstantExpr>>(x.t)}) {
+          std::get<std::optional<parser::ScalarIntConstantExpr>>(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<std::optional<VariableCategory>>(x.t)) {
+  if (!std::get<std::optional<VariableCategory>>(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<dirNameModifier, OmpDirectiveSet>
       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<std::optional<dirNameModifier>>(x.t)}) {
+          std::get<std::optional<dirNameModifier>>(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<parser::OmpLinearClause::WithModifier>(x.u)) {
+    if (std::holds_alternative<parser::OmpLinearClause::WithModifier>(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<std::optional<parser::OmpMapType>>(x.t)}) {
+
+  if (const auto &maptype{std::get<std::optional<parser::OmpMapType>>(x.v.t)}) {
     using Type = parser::OmpMapType::Type;
     const Type &type{std::get<Type>(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<std::optional<parser::ScalarIntExpr>>(x.t)}) {
+      if (const auto &chunkExpr{std::get<std::optional<parser::ScalarIntExpr>>(
+              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<parser::OmpDependClause::InOut>(&x.u)}) {
+  if (const auto *inOut{std::get_if<parser::OmpDependClause::InOut>(&x.v.u)}) {
     const auto &designators{std::get<std::list<parser::Designator>>(inOut->t)};
     for (const auto &ele : designators) {
       if (const auto *dataRef{std::get_if<parser::DataRef>(&ele.u)}) {
diff --git a/lib/Semantics/check-omp-structure.h b/lib/Semantics/check-omp-structure.h
index c9e90ef..0f42079 100644
--- a/lib/Semantics/check-omp-structure.h
+++ b/lib/Semantics/check-omp-structure.h
@@ -127,50 +127,6 @@
 
   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 &);
 
   void Enter(const parser::OmpAtomicRead &);
   void Leave(const parser::OmpAtomicRead &);
@@ -180,13 +136,9 @@
   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 &);
+
+#define GEN_FLANG_CLAUSE_CHECK_ENTER
+#include "llvm/Frontend/OpenMP/OMP.inc"
 
 private:
   bool HasInvalidWorksharingNesting(