[Flang][OpenMP][OpenACC] Add function for mapping parser clause classes with the corresponding clause kind.

1. Generate the mapping for clauses between the parser class and the
   corresponding clause kind for OpenMP and OpenACC using tablegen.

2. Add a common function to get the OmpObjectList from the OpenMP
   clauses to avoid repetition of code.

Reviewed by: Kiranchandramohan @kiranchandramohan , Valentin Clement @clementval

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

GitOrigin-RevId: 1d7960a601fc83b3847f83681573019271e7516f
diff --git a/lib/Semantics/check-omp-structure.cpp b/lib/Semantics/check-omp-structure.cpp
index b23ae51..baa31fd 100644
--- a/lib/Semantics/check-omp-structure.cpp
+++ b/lib/Semantics/check-omp-structure.cpp
@@ -840,7 +840,6 @@
 
 void OmpStructureChecker::CheckMultipleAppearanceAcrossContext(
     const parser::OmpObjectList &redObjectList) {
-  const parser::OmpObjectList *objList{nullptr};
   //  TODO: Verify the assumption here that the immediately enclosing region is
   //  the parallel region to which the worksharing construct having reduction
   //  binds to.
@@ -848,43 +847,29 @@
     for (auto it : enclosingContext->clauseInfo) {
       llvmOmpClause type = it.first;
       const auto *clause = it.second;
-      if (type == llvm::omp::Clause::OMPC_private) {
-        const auto &pClause{std::get<parser::OmpClause::Private>(clause->u)};
-        objList = &pClause.v;
-      } else if (type == llvm::omp::Clause::OMPC_firstprivate) {
-        const auto &fpClause{
-            std::get<parser::OmpClause::Firstprivate>(clause->u)};
-        objList = &fpClause.v;
-      } else if (type == llvm::omp::Clause::OMPC_lastprivate) {
-        const auto &lpClause{
-            std::get<parser::OmpClause::Lastprivate>(clause->u)};
-        objList = &lpClause.v;
-      } else if (type == llvm::omp::Clause::OMPC_reduction) {
-        const auto &rClause{std::get<parser::OmpClause::Reduction>(clause->u)};
-        const auto &olist{std::get<1>(rClause.v.t)};
-        objList = &olist;
-      }
-      if (objList) {
-        for (const auto &ompObject : objList->v) {
-          if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
-            if (const auto *symbol{name->symbol}) {
-              for (const auto &redOmpObject : redObjectList.v) {
-                if (const auto *rname{
-                        parser::Unwrap<parser::Name>(redOmpObject)}) {
-                  if (const auto *rsymbol{rname->symbol}) {
-                    if (rsymbol->name() == symbol->name()) {
-                      context_.Say(GetContext().clauseSource,
-                          "%s variable '%s' is %s in outer context must"
-                          " be shared in the parallel regions to which any"
-                          " of the worksharing regions arising from the "
-                          "worksharing"
-                          " construct bind."_err_en_US,
-                          parser::ToUpperCaseLetters(
-                              getClauseName(llvm::omp::Clause::OMPC_reduction)
-                                  .str()),
-                          symbol->name(),
-                          parser::ToUpperCaseLetters(
-                              getClauseName(type).str()));
+      if (llvm::omp::privateReductionSet.test(type)) {
+        if (const auto *objList{GetOmpObjectList(*clause)}) {
+          for (const auto &ompObject : objList->v) {
+            if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
+              if (const auto *symbol{name->symbol}) {
+                for (const auto &redOmpObject : redObjectList.v) {
+                  if (const auto *rname{
+                          parser::Unwrap<parser::Name>(redOmpObject)}) {
+                    if (const auto *rsymbol{rname->symbol}) {
+                      if (rsymbol->name() == symbol->name()) {
+                        context_.Say(GetContext().clauseSource,
+                            "%s variable '%s' is %s in outer context must"
+                            " be shared in the parallel regions to which any"
+                            " of the worksharing regions arising from the "
+                            "worksharing"
+                            " construct bind."_err_en_US,
+                            parser::ToUpperCaseLetters(
+                                getClauseName(llvm::omp::Clause::OMPC_reduction)
+                                    .str()),
+                            symbol->name(),
+                            parser::ToUpperCaseLetters(
+                                getClauseName(type).str()));
+                      }
                     }
                   }
                 }
@@ -1213,7 +1198,7 @@
   DirectivesClauseTriple dirClauseTriple;
   SymbolSourceMap currSymbols;
   GetSymbolsInObjectList(x.v, currSymbols);
-  CheckDefinableObjects(currSymbols, llvm::omp::Clause::OMPC_lastprivate);
+  CheckDefinableObjects(currSymbols, GetClauseKindForParserClass(x));
 
   // Check lastprivate variables in worksharing constructs
   dirClauseTriple.emplace(llvm::omp::Directive::OMPD_do,
@@ -1224,7 +1209,7 @@
           llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet));
 
   CheckPrivateSymbolsInOuterCxt(
-      currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_lastprivate);
+      currSymbols, dirClauseTriple, GetClauseKindForParserClass(x));
 }
 
 llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) {
@@ -1368,40 +1353,11 @@
     if (auto *enclosingContext{GetEnclosingContextWithDir(enclosingDir)}) {
       for (auto it{enclosingContext->clauseInfo.begin()};
            it != enclosingContext->clauseInfo.end(); ++it) {
-        // TODO: Replace the hard-coded clause names by using autogen checks or
-        // a function which maps parser::OmpClause::<name> to the corresponding
-        // llvm::omp::Clause::OMPC_<name>
-        std::visit(common::visitors{
-                       [&](const parser::OmpClause::Private &x) {
-                         if (enclosingClauseSet.test(
-                                 llvm::omp::Clause::OMPC_private)) {
-                           GetSymbolsInObjectList(x.v, enclosingSymbols);
-                         }
-                       },
-                       [&](const parser::OmpClause::Firstprivate &x) {
-                         if (enclosingClauseSet.test(
-                                 llvm::omp::Clause::OMPC_firstprivate)) {
-                           GetSymbolsInObjectList(x.v, enclosingSymbols);
-                         }
-                       },
-                       [&](const parser::OmpClause::Lastprivate &x) {
-                         if (enclosingClauseSet.test(
-                                 llvm::omp::Clause::OMPC_lastprivate)) {
-                           GetSymbolsInObjectList(x.v, enclosingSymbols);
-                         }
-                       },
-                       [&](const parser::OmpClause::Reduction &x) {
-                         if (enclosingClauseSet.test(
-                                 llvm::omp::Clause::OMPC_reduction)) {
-                           const auto &ompObjectList{
-                               std::get<parser::OmpObjectList>(x.v.t)};
-                           GetSymbolsInObjectList(
-                               ompObjectList, enclosingSymbols);
-                         }
-                       },
-                       [&](const auto &) {},
-                   },
-            it->second->u);
+        if (enclosingClauseSet.test(it->first)) {
+          if (const auto *ompObjectList{GetOmpObjectList(*it->second)}) {
+            GetSymbolsInObjectList(*ompObjectList, enclosingSymbols);
+          }
+        }
       }
 
       // Check if the symbols in current context are private in outer context
@@ -1497,4 +1453,37 @@
   }
 }
 
+const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
+    const parser::OmpClause &clause) {
+
+  // Clauses with OmpObjectList as its data member
+  using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate,
+      parser::OmpClause::Copyin, parser::OmpClause::Firstprivate,
+      parser::OmpClause::From, parser::OmpClause::Lastprivate,
+      parser::OmpClause::Link, parser::OmpClause::Private,
+      parser::OmpClause::Shared, parser::OmpClause::To>;
+
+  // Clauses with OmpObjectList in the tuple
+  using TupleObjectListClauses = std::tuple<parser::OmpClause::Allocate,
+      parser::OmpClause::Map, parser::OmpClause::Reduction>;
+
+  // TODO:: Generate the tuples using TableGen.
+  // Handle other constructs with OmpObjectList such as OpenMPThreadprivate.
+  return std::visit(
+      common::visitors{
+          [&](const auto &x) -> const parser::OmpObjectList * {
+            using Ty = std::decay_t<decltype(x)>;
+            if constexpr (common::HasMember<Ty, MemberObjectListClauses>) {
+              return &x.v;
+            } else if constexpr (common::HasMember<Ty,
+                                     TupleObjectListClauses>) {
+              return &(std::get<parser::OmpObjectList>(x.v.t));
+            } else {
+              return nullptr;
+            }
+          },
+      },
+      clause.u);
+}
+
 } // namespace Fortran::semantics
diff --git a/lib/Semantics/check-omp-structure.h b/lib/Semantics/check-omp-structure.h
index cd560dd..f11ddc6 100644
--- a/lib/Semantics/check-omp-structure.h
+++ b/lib/Semantics/check-omp-structure.h
@@ -153,6 +153,13 @@
 #define GEN_FLANG_CLAUSE_CHECK_ENTER
 #include "llvm/Frontend/OpenMP/OMP.inc"
 
+  // Get the OpenMP Clause Kind for the corresponding Parser class
+  template <typename A>
+  llvm::omp::Clause GetClauseKindForParserClass(const A &) {
+#define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
+#include "llvm/Frontend/OpenMP/OMP.inc"
+  }
+
 private:
   bool HasInvalidWorksharingNesting(
       const parser::CharBlock &, const OmpDirectiveSet &);
@@ -197,6 +204,7 @@
       const parser::Name &name, const llvm::omp::Clause clause);
   void CheckMultipleAppearanceAcrossContext(
       const parser::OmpObjectList &ompObjectList);
+  const parser::OmpObjectList *GetOmpObjectList(const parser::OmpClause &);
 };
 } // namespace Fortran::semantics
 #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_