[llvm] bf93edc - [flang][directives] Use TableGen information for clause classes in parse-tree

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 11 06:43:19 PDT 2020


Author: Valentin Clement
Date: 2020-08-11T09:43:11-04:00
New Revision: bf93edc4758b512e84b70ec6335d15b0cf386a18

URL: https://github.com/llvm/llvm-project/commit/bf93edc4758b512e84b70ec6335d15b0cf386a18
DIFF: https://github.com/llvm/llvm-project/commit/bf93edc4758b512e84b70ec6335d15b0cf386a18.diff

LOG: [flang][directives] Use TableGen information for clause classes in parse-tree

This patch takes advantage of the directive information and tablegen generation
to replace the clauses class parse tree and in the dump parse tree sections.

Reviewed By: sscalpone

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

Added: 
    

Modified: 
    flang/include/flang/Parser/dump-parse-tree.h
    flang/include/flang/Parser/parse-tree.h
    flang/lib/Evaluate/CMakeLists.txt
    flang/lib/Parser/openacc-parsers.cpp
    flang/lib/Parser/unparse.cpp
    flang/lib/Semantics/CMakeLists.txt
    flang/lib/Semantics/check-acc-structure.cpp
    flang/lib/Semantics/check-acc-structure.h
    flang/lib/Semantics/resolve-directives.cpp
    llvm/include/llvm/Frontend/Directive/DirectiveBase.td
    llvm/include/llvm/Frontend/OpenACC/ACC.td
    llvm/include/llvm/Frontend/OpenMP/OMP.td
    llvm/test/TableGen/directive1.td
    llvm/test/TableGen/directive2.td
    llvm/utils/TableGen/DirectiveEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index e3986b754f83..185a514e648f 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -64,51 +64,8 @@ class ParseTreeDumper {
   NODE(parser, AccBeginLoopDirective)
   NODE(parser, AccBlockDirective)
   NODE(parser, AccClause)
-  NODE(AccClause, Auto)
-  NODE(AccClause, Async)
-  NODE(AccClause, Attach)
-  NODE(AccClause, Bind)
-  NODE(AccClause, Capture)
-  NODE(AccClause, Collapse)
-  NODE(AccClause, Copy)
-  NODE(AccClause, Copyin)
-  NODE(AccClause, Copyout)
-  NODE(AccClause, Create)
-  NODE(AccClause, Default)
-  NODE(AccClause, DefaultAsync)
-  NODE(AccClause, Delete)
-  NODE(AccClause, Detach)
-  NODE(AccClause, Device)
-  NODE(AccClause, DeviceNum)
-  NODE(AccClause, DevicePtr)
-  NODE(AccClause, DeviceResident)
-  NODE(AccClause, DeviceType)
-  NODE(AccClause, Finalize)
-  NODE(AccClause, FirstPrivate)
-  NODE(AccClause, Gang)
-  NODE(AccClause, Host)
-  NODE(AccClause, If)
-  NODE(AccClause, IfPresent)
-  NODE(AccClause, Independent)
-  NODE(AccClause, Link)
-  NODE(AccClause, NoCreate)
-  NODE(AccClause, NoHost)
-  NODE(AccClause, NumGangs)
-  NODE(AccClause, NumWorkers)
-  NODE(AccClause, Present)
-  NODE(AccClause, Private)
-  NODE(AccClause, Tile)
-  NODE(AccClause, UseDevice)
-  NODE(AccClause, Read)
-  NODE(AccClause, Reduction)
-  NODE(AccClause, Self)
-  NODE(AccClause, Seq)
-  NODE(AccClause, Vector)
-  NODE(AccClause, VectorLength)
-  NODE(AccClause, Wait)
-  NODE(AccClause, Worker)
-  NODE(AccClause, Write)
-  NODE(AccClause, Unknown)
+#define GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+#include "llvm/Frontend/OpenACC/ACC.cpp.inc"
   NODE(parser, AccDefaultClause)
   NODE_ENUM(parser::AccDefaultClause, Arg)
   NODE(parser, AccClauseList)
@@ -501,38 +458,8 @@ class ParseTreeDumper {
   NODE_ENUM(OmpCancelType, Type)
   NODE(parser, OmpClause)
   NODE(parser, OmpClauseList)
-  NODE(OmpClause, Collapse)
-  NODE(OmpClause, Copyin)
-  NODE(OmpClause, Copyprivate)
-  NODE(OmpClause, Device)
-  NODE(OmpClause, DistSchedule)
-  NODE(OmpClause, Final)
-  NODE(OmpClause, Firstprivate)
-  NODE(OmpClause, From)
-  NODE(OmpClause, Grainsize)
-  NODE(OmpClause, Inbranch)
-  NODE(OmpClause, Lastprivate)
-  NODE(OmpClause, Mergeable)
-  NODE(OmpClause, Nogroup)
-  NODE(OmpClause, Notinbranch)
-  NODE(OmpClause, Threads)
-  NODE(OmpClause, Simd)
-  NODE(OmpClause, NumTasks)
-  NODE(OmpClause, NumTeams)
-  NODE(OmpClause, NumThreads)
-  NODE(OmpClause, Ordered)
-  NODE(OmpClause, Priority)
-  NODE(OmpClause, Private)
-  NODE(OmpClause, Safelen)
-  NODE(OmpClause, Shared)
-  NODE(OmpClause, Simdlen)
-  NODE(OmpClause, ThreadLimit)
-  NODE(OmpClause, To)
-  NODE(OmpClause, Link)
-  NODE(OmpClause, Uniform)
-  NODE(OmpClause, Untied)
-  NODE(OmpClause, UseDevicePtr)
-  NODE(OmpClause, IsDevicePtr)
+#define GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+#include "llvm/Frontend/OpenMP/OMP.cpp.inc"
   NODE(parser, OmpCriticalDirective)
   NODE(OmpCriticalDirective, Hint)
   NODE(parser, OmpDeclareTargetSpecifier)

diff  --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index ebea3331ae5a..c6d5f68c1376 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3459,47 +3459,16 @@ EMPTY_CLASS(OmpNowait);
 // OpenMP Clauses
 struct OmpClause {
   UNION_CLASS_BOILERPLATE(OmpClause);
-  EMPTY_CLASS(Inbranch);
-  EMPTY_CLASS(Mergeable);
-  EMPTY_CLASS(Nogroup);
-  EMPTY_CLASS(Notinbranch);
-  EMPTY_CLASS(Simd);
-  EMPTY_CLASS(Threads);
-  EMPTY_CLASS(Untied);
-  WRAPPER_CLASS(Collapse, ScalarIntConstantExpr);
-  WRAPPER_CLASS(Copyin, OmpObjectList);
-  WRAPPER_CLASS(Copyprivate, OmpObjectList);
-  WRAPPER_CLASS(Device, ScalarIntExpr);
-  WRAPPER_CLASS(DistSchedule, std::optional<ScalarIntExpr>);
-  WRAPPER_CLASS(Final, ScalarLogicalExpr);
-  WRAPPER_CLASS(Firstprivate, OmpObjectList);
-  WRAPPER_CLASS(From, OmpObjectList);
-  WRAPPER_CLASS(Grainsize, ScalarIntExpr);
-  WRAPPER_CLASS(IsDevicePtr, std::list<Name>);
-  WRAPPER_CLASS(Lastprivate, OmpObjectList);
-  WRAPPER_CLASS(Link, OmpObjectList);
-  WRAPPER_CLASS(NumTasks, ScalarIntExpr);
-  WRAPPER_CLASS(NumTeams, ScalarIntExpr);
-  WRAPPER_CLASS(NumThreads, ScalarIntExpr);
-  WRAPPER_CLASS(Ordered, std::optional<ScalarIntConstantExpr>);
-  WRAPPER_CLASS(Priority, ScalarIntExpr);
-  WRAPPER_CLASS(Private, OmpObjectList);
-  WRAPPER_CLASS(Safelen, ScalarIntConstantExpr);
-  WRAPPER_CLASS(Shared, OmpObjectList);
-  WRAPPER_CLASS(Simdlen, ScalarIntConstantExpr);
-  WRAPPER_CLASS(ThreadLimit, ScalarIntExpr);
-  WRAPPER_CLASS(To, OmpObjectList);
-  WRAPPER_CLASS(Uniform, std::list<Name>);
-  WRAPPER_CLASS(UseDevicePtr, std::list<Name>);
+
+#define GEN_FLANG_CLAUSE_PARSER_CLASSES
+#include "llvm/Frontend/OpenMP/OMP.cpp.inc"
+
   CharBlock source;
-  std::variant<Inbranch, Mergeable, Nogroup, Notinbranch, OmpNowait, Untied,
-      Threads, Simd, Collapse, Copyin, Copyprivate, Device, DistSchedule, Final,
-      Firstprivate, From, Grainsize, Lastprivate, NumTasks, NumTeams,
-      NumThreads, Ordered, Priority, Private, Safelen, Shared, Simdlen,
-      ThreadLimit, To, Link, Uniform, UseDevicePtr, IsDevicePtr,
-      OmpAlignedClause, OmpAllocateClause, OmpDefaultClause,
-      OmpDefaultmapClause, OmpDependClause, OmpIfClause, OmpLinearClause,
-      OmpMapClause, OmpProcBindClause, OmpReductionClause, OmpScheduleClause>
+
+  std::variant<
+#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+#include "llvm/Frontend/OpenMP/OMP.cpp.inc"
+      >
       u;
 };
 
@@ -3895,60 +3864,15 @@ struct AccGangArgument {
 struct AccClause {
   UNION_CLASS_BOILERPLATE(AccClause);
 
-  EMPTY_CLASS(Auto);
-  WRAPPER_CLASS(Async, std::optional<ScalarIntExpr>);
-  WRAPPER_CLASS(Attach, AccObjectList);
-  WRAPPER_CLASS(Bind, Name);
-  EMPTY_CLASS(Capture);
-  WRAPPER_CLASS(Collapse, ScalarIntConstantExpr);
-  WRAPPER_CLASS(Copy, AccObjectList);
-  WRAPPER_CLASS(Copyin, AccObjectListWithModifier);
-  WRAPPER_CLASS(Copyout, AccObjectListWithModifier);
-  WRAPPER_CLASS(Create, AccObjectListWithModifier);
-  WRAPPER_CLASS(Default, AccDefaultClause);
-  WRAPPER_CLASS(DefaultAsync, ScalarIntExpr);
-  WRAPPER_CLASS(Delete, AccObjectList);
-  WRAPPER_CLASS(Detach, AccObjectList);
-  WRAPPER_CLASS(Device, AccObjectList);
-  WRAPPER_CLASS(DeviceNum, ScalarIntConstantExpr);
-  WRAPPER_CLASS(DevicePtr, AccObjectList);
-  WRAPPER_CLASS(DeviceResident, AccObjectList);
-  WRAPPER_CLASS(DeviceType, std::optional<std::list<Name>>);
-  EMPTY_CLASS(Finalize);
-  WRAPPER_CLASS(FirstPrivate, AccObjectList);
-  WRAPPER_CLASS(Gang, std::optional<AccGangArgument>);
-  WRAPPER_CLASS(Host, AccObjectList);
-  WRAPPER_CLASS(If, ScalarLogicalExpr);
-  EMPTY_CLASS(IfPresent);
-  EMPTY_CLASS(Independent);
-  WRAPPER_CLASS(Link, AccObjectList);
-  WRAPPER_CLASS(NoCreate, AccObjectList);
-  EMPTY_CLASS(NoHost);
-  WRAPPER_CLASS(NumGangs, ScalarIntExpr);
-  WRAPPER_CLASS(NumWorkers, ScalarIntExpr);
-  WRAPPER_CLASS(Present, AccObjectList);
-  WRAPPER_CLASS(Private, AccObjectList);
-  WRAPPER_CLASS(Tile, AccSizeExprList);
-  WRAPPER_CLASS(UseDevice, AccObjectList);
-  EMPTY_CLASS(Read);
-  WRAPPER_CLASS(Reduction, AccObjectListWithReduction);
-  WRAPPER_CLASS(Self, std::optional<ScalarLogicalExpr>);
-  EMPTY_CLASS(Seq);
-  WRAPPER_CLASS(Vector, std::optional<ScalarIntExpr>);
-  WRAPPER_CLASS(VectorLength, ScalarIntExpr);
-  WRAPPER_CLASS(Wait, std::optional<AccWaitArgument>);
-  WRAPPER_CLASS(Worker, std::optional<ScalarIntExpr>);
-  EMPTY_CLASS(Write);
-  EMPTY_CLASS(Unknown);
+#define GEN_FLANG_CLAUSE_PARSER_CLASSES
+#include "llvm/Frontend/OpenACC/ACC.cpp.inc"
 
   CharBlock source;
 
-  std::variant<Auto, Async, Attach, Bind, Capture, Collapse, Copy, Copyin,
-      Copyout, Create, Default, DefaultAsync, Delete, Detach, Device, DeviceNum,
-      DevicePtr, DeviceResident, DeviceType, Finalize, FirstPrivate, Gang, Host,
-      If, IfPresent, Independent, Link, NoCreate, NoHost, NumGangs, NumWorkers,
-      Present, Private, Tile, UseDevice, Read, Reduction, Self, Seq, Vector,
-      VectorLength, Wait, Worker, Write, Unknown>
+  std::variant<
+#define GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+#include "llvm/Frontend/OpenACC/ACC.cpp.inc"
+      >
       u;
 };
 

diff  --git a/flang/lib/Evaluate/CMakeLists.txt b/flang/lib/Evaluate/CMakeLists.txt
index 9ab83d7c1c25..2a60dd7b85b4 100644
--- a/flang/lib/Evaluate/CMakeLists.txt
+++ b/flang/lib/Evaluate/CMakeLists.txt
@@ -45,6 +45,7 @@ add_flang_library(FortranEvaluate
   ${LIBPGMATH}
 
   DEPENDS
+  acc_gen
   omp_gen
 )
 

diff  --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp
index a2ab628c0993..0a61921c9087 100644
--- a/flang/lib/Parser/openacc-parsers.cpp
+++ b/flang/lib/Parser/openacc-parsers.cpp
@@ -55,7 +55,7 @@ TYPE_PARSER("AUTO" >> construct<AccClause>(construct<AccClause::Auto>()) ||
                     parenthesized(Parser<AccObjectList>{}))) ||
     "DEVICE" >> construct<AccClause>(construct<AccClause::Device>(
                     parenthesized(Parser<AccObjectList>{}))) ||
-    "DEVICEPTR" >> construct<AccClause>(construct<AccClause::DevicePtr>(
+    "DEVICEPTR" >> construct<AccClause>(construct<AccClause::Deviceptr>(
                        parenthesized(Parser<AccObjectList>{}))) ||
     "DEVICENUM" >> construct<AccClause>(construct<AccClause::DeviceNum>(
                        parenthesized(scalarIntConstantExpr))) ||
@@ -69,7 +69,7 @@ TYPE_PARSER("AUTO" >> construct<AccClause>(construct<AccClause::Auto>()) ||
         construct<AccClause>(construct<AccClause::DeviceType>(
             parenthesized(maybe(nonemptyList(name))))) ||
     "FINALIZE" >> construct<AccClause>(construct<AccClause::Finalize>()) ||
-    "FIRSTPRIVATE" >> construct<AccClause>(construct<AccClause::FirstPrivate>(
+    "FIRSTPRIVATE" >> construct<AccClause>(construct<AccClause::Firstprivate>(
                           parenthesized(Parser<AccObjectList>{}))) ||
     "GANG" >> construct<AccClause>(construct<AccClause::Gang>(
                   maybe(parenthesized(Parser<AccGangArgument>{})))) ||
@@ -84,7 +84,7 @@ TYPE_PARSER("AUTO" >> construct<AccClause>(construct<AccClause::Auto>()) ||
                   parenthesized(Parser<AccObjectList>{}))) ||
     "NO_CREATE" >> construct<AccClause>(construct<AccClause::NoCreate>(
                        parenthesized(Parser<AccObjectList>{}))) ||
-    "NOHOST" >> construct<AccClause>(construct<AccClause::NoHost>()) ||
+    "NOHOST" >> construct<AccClause>(construct<AccClause::Nohost>()) ||
     "NUM_GANGS" >> construct<AccClause>(construct<AccClause::NumGangs>(
                        parenthesized(scalarIntExpr))) ||
     "NUM_WORKERS" >> construct<AccClause>(construct<AccClause::NumWorkers>(

diff  --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index ab18d026e74e..1093cb21709c 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1835,7 +1835,7 @@ class UnparseVisitor {
   void Before(const AccClause::Finalize &) { Word("FINALIZE"); }
   void Before(const AccClause::IfPresent &) { Word("IF_PRESENT"); }
   void Before(const AccClause::Independent &) { Word("INDEPENDENT"); }
-  void Before(const AccClause::NoHost &) { Word("NOHOST"); }
+  void Before(const AccClause::Nohost &) { Word("NOHOST"); }
   void Before(const AccClause::Read &) { Word("READ"); }
   void Before(const AccClause::Seq &) { Word("SEQ"); }
   void Before(const AccClause::Write &) { Word("WRITE"); }
@@ -1906,7 +1906,7 @@ class UnparseVisitor {
     Walk(x.v);
     Put(")");
   }
-  void Unparse(const AccClause::DevicePtr &x) {
+  void Unparse(const AccClause::Deviceptr &x) {
     Word("DEVICEPTR");
     Put("(");
     Walk(x.v);
@@ -1918,7 +1918,7 @@ class UnparseVisitor {
     Walk(x.v);
     Put(")");
   }
-  void Unparse(const AccClause::FirstPrivate &x) {
+  void Unparse(const AccClause::Firstprivate &x) {
     Word("FIRSTPRIVATE");
     Put("(");
     Walk(x.v);

diff  --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt
index d82926220b3e..9eb521ecc060 100644
--- a/flang/lib/Semantics/CMakeLists.txt
+++ b/flang/lib/Semantics/CMakeLists.txt
@@ -44,6 +44,7 @@ add_flang_library(FortranSemantics
   unparse-with-symbols.cpp
 
   DEPENDS
+  acc_gen
   omp_gen
 
   LINK_LIBS

diff  --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp
index 46ccc2b762f5..311a7c4d3328 100644
--- a/flang/lib/Semantics/check-acc-structure.cpp
+++ b/flang/lib/Semantics/check-acc-structure.cpp
@@ -263,11 +263,11 @@ 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(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)
+CHECK_SIMPLE_CLAUSE(Firstprivate, ACCC_firstprivate)
 CHECK_SIMPLE_CLAUSE(Gang, ACCC_gang)
 CHECK_SIMPLE_CLAUSE(Host, ACCC_host)
 CHECK_SIMPLE_CLAUSE(If, ACCC_if)
@@ -275,7 +275,7 @@ 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(Nohost, ACCC_nohost)
 CHECK_SIMPLE_CLAUSE(NumGangs, ACCC_num_gangs)
 CHECK_SIMPLE_CLAUSE(NumWorkers, ACCC_num_workers)
 CHECK_SIMPLE_CLAUSE(Present, ACCC_present)

diff  --git a/flang/lib/Semantics/check-acc-structure.h b/flang/lib/Semantics/check-acc-structure.h
index 1ce6e9052b03..efed05d42869 100644
--- a/flang/lib/Semantics/check-acc-structure.h
+++ b/flang/lib/Semantics/check-acc-structure.h
@@ -76,11 +76,11 @@ class AccStructureChecker
   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::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::Firstprivate &);
   void Enter(const parser::AccClause::Gang &);
   void Enter(const parser::AccClause::Host &);
   void Enter(const parser::AccClause::If &);
@@ -88,7 +88,7 @@ class AccStructureChecker
   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::Nohost &);
   void Enter(const parser::AccClause::NumGangs &);
   void Enter(const parser::AccClause::NumWorkers &);
   void Enter(const parser::AccClause::Present &);

diff  --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index d05eb5385ba8..e73bfa7c37cc 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -173,7 +173,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
     ResolveAccObjectList(x.v, Symbol::Flag::AccPrivate);
     return false;
   }
-  bool Pre(const parser::AccClause::FirstPrivate &x) {
+  bool Pre(const parser::AccClause::Firstprivate &x) {
     ResolveAccObjectList(x.v, Symbol::Flag::AccFirstPrivate);
     return false;
   }

diff  --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
index 26049ca60db3..13b1edef0580 100644
--- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
+++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td
@@ -46,6 +46,9 @@ class DirectiveLanguage {
 
   // EnumSet class name used for clauses to generated the allowed clauses map.
   string clauseEnumSetClass = "";
+
+  // Class holding the clauses in the flang parse-tree.
+  string flangClauseBaseClass = "";
 }
 
 // Information about a specific clause.
@@ -57,10 +60,20 @@ class Clause<string c> {
   string alternativeName = "";
 
   // Optional class holding value of the clause in clang AST.
-  string clangClass = ?;
+  string clangClass = "";
+
+  // Optional class holding the clause in flang AST. If left blank, the class
+  // is assumed to be the name of the clause with capitalized word and
+  // underscores removed.
+  // ex: async -> Async
+  //     num_threads -> NumThreads
+  string flangClass = "";
 
   // Optional class holding value of the clause in flang AST.
-  string flangClass = ?;
+  string flangClassValue = "";
+
+  // If set to 1, value is optional. Not optional by default.
+  bit isValueOptional = 0;
 
   // Is clause implicit? If clause is set as implicit, the default kind will
   // be return in get<LanguageName>ClauseKind instead of their own kind.

diff  --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td
index 4dbf4bbc0fb0..4c686aad050b 100644
--- a/llvm/include/llvm/Frontend/OpenACC/ACC.td
+++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td
@@ -25,28 +25,30 @@ def OpenACC : DirectiveLanguage {
   let enableBitmaskEnumInNamespace = 1;
   let includeHeader = "llvm/Frontend/OpenACC/ACC.h.inc";
   let clauseEnumSetClass = "AccClauseSet";
+  let flangClauseBaseClass = "AccClause";
 }
 
 //===----------------------------------------------------------------------===//
 // Definition of OpenACC clauses
 //===----------------------------------------------------------------------===//
 
-// 2.9.6
-def ACCC_Auto : Clause<"auto"> {}
-
 // 2.16.1
 def ACCC_Async : Clause<"async"> {
-  let flangClass = "std::optional<ScalarIntExpr>";
+  let flangClassValue = "ScalarIntExpr";
+  let isValueOptional = 1;
 }
 
+// 2.9.6
+def ACCC_Auto : Clause<"auto"> {}
+
 // 2.7.11
 def ACCC_Attach : Clause<"attach"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.15.1
 def ACCC_Bind : Clause<"bind"> {
-  let flangClass = "Name";
+  let flangClassValue = "Name";
 }
 
 // 2.12
@@ -55,72 +57,73 @@ def ACCC_Capture : Clause<"capture"> {
 
 // 2.9.1
 def ACCC_Collapse : Clause<"collapse"> {
-  let flangClass = "ScalarIntConstantExpr";
+  let flangClassValue = "ScalarIntConstantExpr";
 }
 
 // 2.7.5
 def ACCC_Copy : Clause<"copy"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 // 2.7.6
 def ACCC_Copyin : Clause<"copyin"> {
-  let flangClass = "AccObjectListWithModifier";
+  let flangClassValue = "AccObjectListWithModifier";
 }
 
 // 2.7.7
 def ACCC_Copyout : Clause<"copyout"> {
-  let flangClass = "AccObjectListWithModifier";
+  let flangClassValue = "AccObjectListWithModifier";
 }
 
 // 2.7.8
 def ACCC_Create : Clause<"create"> {
-  let flangClass = "AccObjectListWithModifier";
+  let flangClassValue = "AccObjectListWithModifier";
 }
 
 // 2.5.14
 def ACCC_Default : Clause<"default"> {
-  let flangClass = "AccDefaultClause";
+  let flangClassValue = "AccDefaultClause";
 }
 
 // 2.4.12
 def ACCC_DefaultAsync : Clause<"default_async"> {
-  let flangClass = "ScalarIntExpr";
+  let flangClassValue = "ScalarIntExpr";
 }
 
 // 2.7.10
 def ACCC_Delete : Clause<"delete"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.7.12
 def ACCC_Detach : Clause<"detach"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.14.4
 def ACCC_Device : Clause<"device"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.14.1
 def ACCC_DeviceNum : Clause<"device_num">  {
-  let flangClass = "ScalarIntConstantExpr";
+  let flangClassValue = "ScalarIntConstantExpr";
 }
 
 // 2.7.3
 def ACCC_DevicePtr : Clause<"deviceptr"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.13
 def ACCC_DeviceResident : Clause<"device_resident"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.4
 def ACCC_DeviceType : Clause<"device_type"> {
   // (DeviceType, "*"
-  let flangClass = "std::optional<std::list<Name>>";
+  let flangClassValue = "std::list<Name>";
+  let isValueOptional = 1;
 }
 
 // 2.6.6
@@ -128,22 +131,23 @@ def ACCC_Finalize : Clause<"finalize"> {}
 
 // 2.5.12
 def ACCC_FirstPrivate : Clause<"firstprivate"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.9.2
 def ACCC_Gang : Clause<"gang"> {
-  let flangClass = "std::optional<AccGangArgument>";
+  let flangClassValue = "AccGangArgument";
+  let isValueOptional = 1;
 }
 
 // 2.14.4
 def ACCC_Host : Clause<"host"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.5.4
 def ACCC_If : Clause <"if"> {
-  let flangClass = "ScalarLogicalExpr";
+  let flangClassValue = "ScalarLogicalExpr";
 }
 
 // 2.14.4
@@ -154,12 +158,12 @@ def ACCC_Independent : Clause<"independent"> {}
 
 // 2.13
 def ACCC_Link : Clause<"link"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.7.9
 def ACCC_NoCreate : Clause<"no_create"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.15.1
@@ -167,32 +171,32 @@ def ACCC_NoHost : Clause<"nohost"> {}
 
 // 2.5.8
 def ACCC_NumGangs : Clause<"num_gangs"> {
-  let flangClass = "ScalarIntExpr";
+  let flangClassValue = "ScalarIntExpr";
 }
 
 // 2.5.9
 def ACCC_NumWorkers : Clause<"num_workers"> {
-  let flangClass = "ScalarIntExpr";
+  let flangClassValue = "ScalarIntExpr";
 }
 
 // 2.7.4
 def ACCC_Present : Clause<"present"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.5.11
 def ACCC_Private : Clause<"private"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.9.7
 def ACCC_Tile : Clause <"tile"> {
-  let flangClass = "AccSizeExprList";
+  let flangClassValue = "AccSizeExprList";
 }
 
 // 2.8.1
 def ACCC_UseDevice : Clause <"use_device"> {
-  let flangClass = "AccObjectList";
+  let flangClassValue = "AccObjectList";
 }
 
 // 2.12
@@ -200,12 +204,13 @@ def ACCC_Read : Clause<"read"> {}
 
 // 2.5.13
 def ACCC_Reduction : Clause<"reduction"> {
-  let flangClass = "AccObjectListWithReduction";
+  let flangClassValue = "AccObjectListWithReduction";
 }
 
 // 2.5.5
 def ACCC_Self : Clause<"self"> {
-  let flangClass = "std::optional<ScalarLogicalExpr>";
+  let flangClassValue = "ScalarLogicalExpr";
+  let isValueOptional = 1;
 }
 
 // 2.9.5
@@ -213,22 +218,25 @@ def ACCC_Seq : Clause<"seq"> {}
 
 // 2.9.4
 def ACCC_Vector : Clause<"vector"> {
-  let flangClass = "std::optional<ScalarIntExpr>";
+  let flangClassValue = "ScalarIntExpr";
+  let isValueOptional = 1;
 }
 
 // 2.5.10
 def ACCC_VectorLength : Clause<"vector_length"> {
-  let flangClass = "ScalarIntExpr";
+  let flangClassValue = "ScalarIntExpr";
 }
 
 // 2.16.2
 def ACCC_Wait : Clause<"wait"> {
-  let flangClass = "std::optional<AccWaitArgument>";
+  let flangClassValue = "AccWaitArgument";
+  let isValueOptional = 1;
 }
 
 // 2.9.3
 def ACCC_Worker: Clause<"worker"> {
-  let flangClass = "std::optional<ScalarIntExpr>";
+  let flangClassValue = "ScalarIntExpr";
+  let isValueOptional = 1;
 }
 
 // 2.12

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index a0d694533e4d..24111c9e4701 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -25,6 +25,7 @@ def OpenMP : DirectiveLanguage {
   let enableBitmaskEnumInNamespace = 1;
   let includeHeader = "llvm/Frontend/OpenMP/OMP.h.inc";
   let clauseEnumSetClass = "OmpClauseSet";
+  let flangClauseBaseClass = "OmpClause";
 }
 
 //===----------------------------------------------------------------------===//
@@ -34,38 +35,87 @@ def OpenMP : DirectiveLanguage {
 def OMPC_Allocator : Clause<"allocator"> {
   let clangClass = "OMPAllocatorClause";
 }
-def OMPC_If : Clause<"if"> { let clangClass = "OMPIfClause"; }
-def OMPC_Final : Clause<"final"> { let clangClass = "OMPFinalClause"; }
+def OMPC_If : Clause<"if"> {
+  let clangClass = "OMPIfClause";
+  let flangClass = "OmpIfClause";
+}
+def OMPC_Final : Clause<"final"> {
+  let clangClass = "OMPFinalClause";
+  let flangClassValue = "ScalarLogicalExpr";
+}
 def OMPC_NumThreads : Clause<"num_threads"> {
   let clangClass = "OMPNumThreadsClause";
+  let flangClassValue = "ScalarIntExpr";
+}
+def OMPC_SafeLen : Clause<"safelen"> {
+  let clangClass = "OMPSafelenClause";
+  let flangClassValue = "ScalarIntConstantExpr";
+}
+def OMPC_SimdLen : Clause<"simdlen"> {
+  let clangClass = "OMPSimdlenClause";
+  let flangClassValue = "ScalarIntConstantExpr";
+}
+def OMPC_Collapse : Clause<"collapse"> {
+  let clangClass = "OMPCollapseClause";
+  let flangClassValue = "ScalarIntConstantExpr";
+}
+def OMPC_Default : Clause<"default"> {
+  let clangClass = "OMPDefaultClause";
+  let flangClass = "OmpDefaultClause";
+}
+def OMPC_Private : Clause<"private"> {
+  let clangClass = "OMPPrivateClause";
+  let flangClassValue = "OmpObjectList";
 }
-def OMPC_SafeLen : Clause<"safelen"> { let clangClass = "OMPSafelenClause"; }
-def OMPC_SimdLen : Clause<"simdlen"> { let clangClass = "OMPSimdlenClause"; }
-def OMPC_Collapse : Clause<"collapse"> { let clangClass = "OMPCollapseClause"; }
-def OMPC_Default : Clause<"default"> { let clangClass = "OMPDefaultClause"; }
-def OMPC_Private : Clause<"private"> { let clangClass = "OMPPrivateClause"; }
 def OMPC_FirstPrivate : Clause<"firstprivate"> {
   let clangClass = "OMPFirstprivateClause";
+  let flangClassValue = "OmpObjectList";
 }
 def OMPC_LastPrivate : Clause<"lastprivate"> {
   let clangClass = "OMPLastprivateClause";
+  let flangClassValue = "OmpObjectList";
+}
+def OMPC_Shared : Clause<"shared"> {
+  let clangClass = "OMPSharedClause";
+  let flangClassValue = "OmpObjectList";
 }
-def OMPC_Shared : Clause<"shared"> { let clangClass = "OMPSharedClause"; }
 def OMPC_Reduction : Clause<"reduction"> {
   let clangClass = "OMPReductionClause";
+  let flangClass = "OmpReductionClause";
+}
+def OMPC_Linear : Clause<"linear"> {
+  let clangClass = "OMPLinearClause";
+  let flangClass = "OmpLinearClause";
+}
+def OMPC_Aligned : Clause<"aligned"> {
+  let clangClass = "OMPAlignedClause";
+  let flangClass = "OmpAlignedClause";
+}
+def OMPC_Copyin : Clause<"copyin"> {
+  let clangClass = "OMPCopyinClause";
+  let flangClassValue = "OmpObjectList";
 }
-def OMPC_Linear : Clause<"linear"> { let clangClass = "OMPLinearClause"; }
-def OMPC_Aligned : Clause<"aligned"> { let clangClass = "OMPAlignedClause"; }
-def OMPC_Copyin : Clause<"copyin"> { let clangClass = "OMPCopyinClause"; }
 def OMPC_CopyPrivate : Clause<"copyprivate"> {
   let clangClass = "OMPCopyprivateClause";
+  let flangClassValue = "OmpObjectList";
 }
 def OMPC_ProcBind : Clause<"proc_bind"> {
   let clangClass = "OMPProcBindClause";
+  let flangClass = "OmpProcBindClause";
+}
+def OMPC_Schedule : Clause<"schedule"> {
+  let clangClass = "OMPScheduleClause";
+  let flangClass = "OmpScheduleClause";
+}
+def OMPC_Ordered : Clause<"ordered"> {
+  let clangClass = "OMPOrderedClause";
+  let flangClassValue = "ScalarIntConstantExpr";
+  let isValueOptional = 1;
+}
+def OMPC_NoWait : Clause<"nowait"> {
+  let clangClass = "OMPNowaitClause";
+  let flangClass = "OmpNowait";
 }
-def OMPC_Schedule : Clause<"schedule"> { let clangClass = "OMPScheduleClause"; }
-def OMPC_Ordered : Clause<"ordered"> { let clangClass = "OMPOrderedClause"; }
-def OMPC_NoWait : Clause<"nowait"> { let clangClass = "OMPNowaitClause"; }
 def OMPC_Untied : Clause<"untied"> { let clangClass = "OMPUntiedClause"; }
 def OMPC_Mergeable : Clause<"mergeable"> {
   let clangClass = "OMPMergeableClause";
@@ -79,47 +129,70 @@ def OMPC_AcqRel : Clause<"acq_rel"> { let clangClass = "OMPAcqRelClause"; }
 def OMPC_Acquire : Clause<"acquire"> { let clangClass = "OMPAcquireClause"; }
 def OMPC_Release : Clause<"release"> { let clangClass = "OMPReleaseClause"; }
 def OMPC_Relaxed : Clause<"relaxed"> { let clangClass = "OMPRelaxedClause"; }
-def OMPC_Depend : Clause<"depend"> { let clangClass = "OMPDependClause"; }
-def OMPC_Device : Clause<"device"> { let clangClass = "OMPDeviceClause"; }
+def OMPC_Depend : Clause<"depend"> {
+  let clangClass = "OMPDependClause";
+  let flangClass = "OmpDependClause";
+}
+def OMPC_Device : Clause<"device"> {
+  let clangClass = "OMPDeviceClause";
+  let flangClassValue = "ScalarIntExpr";
+}
 def OMPC_Threads : Clause<"threads"> { let clangClass = "OMPThreadsClause"; }
 def OMPC_Simd : Clause<"simd"> { let clangClass = "OMPSIMDClause"; }
-def OMPC_Map : Clause<"map"> { let clangClass = "OMPMapClause"; }
+def OMPC_Map : Clause<"map"> {
+  let clangClass = "OMPMapClause";
+  let flangClass = "OmpMapClause";
+}
 def OMPC_NumTeams : Clause<"num_teams"> {
   let clangClass = "OMPNumTeamsClause";
+  let flangClassValue = "ScalarIntExpr";
 }
 def OMPC_ThreadLimit : Clause<"thread_limit"> {
   let clangClass = "OMPThreadLimitClause";
+  let flangClassValue = "ScalarIntExpr";
 }
 def OMPC_Priority : Clause<"priority"> {
   let clangClass = "OMPPriorityClause";
+  let flangClassValue = "ScalarIntExpr";
 }
 def OMPC_GrainSize : Clause<"grainsize"> {
   let clangClass = "OMPGrainsizeClause";
+  let flangClassValue = "ScalarIntExpr";
 }
 def OMPC_NoGroup : Clause<"nogroup"> {
   let clangClass = "OMPNogroupClause";
 }
 def OMPC_NumTasks : Clause<"num_tasks"> {
   let clangClass = "OMPNumTasksClause";
+  let flangClassValue = "ScalarIntExpr";
 }
 def OMPC_Hint : Clause<"hint"> {
   let clangClass = "OMPHintClause";
 }
 def OMPC_DistSchedule : Clause<"dist_schedule"> {
   let clangClass = "OMPDistScheduleClause";
+  let flangClassValue = "ScalarIntExpr";
+  let isValueOptional = 1;
 }
 def OMPC_DefaultMap : Clause<"defaultmap"> {
   let clangClass = "OMPDefaultmapClause";
+  let flangClass = "OmpDefaultmapClause";
 }
 def OMPC_To : Clause<"to"> {
   let clangClass = "OMPToClause";
+  let flangClassValue = "OmpObjectList";
+}
+def OMPC_From : Clause<"from"> {
+  let clangClass = "OMPFromClause";
+  let flangClassValue = "OmpObjectList";
 }
-def OMPC_From : Clause<"from"> { let clangClass = "OMPFromClause"; }
 def OMPC_UseDevicePtr : Clause<"use_device_ptr"> {
   let clangClass = "OMPUseDevicePtrClause";
+  let flangClassValue = "std::list<Name>";
 }
 def OMPC_IsDevicePtr : Clause<"is_device_ptr"> {
   let clangClass = "OMPIsDevicePtrClause";
+  let flangClassValue = "std::list<Name>";
 }
 def OMPC_TaskReduction : Clause<"task_reduction"> {
   let clangClass = "OMPTaskReductionClause";
@@ -144,6 +217,7 @@ def OMPC_AtomicDefaultMemOrder : Clause<"atomic_default_mem_order"> {
 }
 def OMPC_Allocate : Clause<"allocate"> {
   let clangClass = "OMPAllocateClause";
+  let flangClass = "OmpAllocateClause";
 }
 def OMPC_NonTemporal : Clause<"nontemporal"> {
   let clangClass = "OMPNontemporalClause";
@@ -172,7 +246,9 @@ def OMPC_Affinity : Clause<"affinity"> {
 def OMPC_UseDeviceAddr : Clause<"use_device_addr"> {
   let clangClass = "OMPUseDeviceAddrClause";
 }
-def OMPC_Uniform : Clause<"uniform"> {}
+def OMPC_Uniform : Clause<"uniform"> {
+  let flangClassValue = "std::list<Name>";
+}
 def OMPC_DeviceType : Clause<"device_type"> {}
 def OMPC_Match : Clause<"match"> {}
 def OMPC_Depobj : Clause<"depobj"> {
@@ -191,7 +267,9 @@ def OMPC_Unknown : Clause<"unknown"> {
   let isImplicit = 1;
   let isDefault = 1;
 }
-def OMPC_Link : Clause<"link"> {}
+def OMPC_Link : Clause<"link"> {
+  let flangClassValue = "OmpObjectList";
+}
 def OMPC_Inbranch : Clause<"inbranch"> {}
 def OMPC_Notinbranch : Clause<"notinbranch"> {}
 

diff  --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td
index 905d6e28c4f9..f647a03814ce 100644
--- a/llvm/test/TableGen/directive1.td
+++ b/llvm/test/TableGen/directive1.td
@@ -12,10 +12,15 @@ def TestDirectiveLanguage : DirectiveLanguage {
   let clausePrefix = "TDLC_";
   let makeEnumAvailableInNamespace = 1;
   let enableBitmaskEnumInNamespace = 1;
+  let flangClauseBaseClass = "TdlClause";
 }
 
-def TDLC_ClauseA : Clause<"clausea"> {}
+def TDLC_ClauseA : Clause<"clausea"> {
+  let flangClass = "TdlClauseA";
+}
 def TDLC_ClauseB : Clause<"clauseb"> {
+  let flangClassValue = "IntExpr";
+  let isValueOptional = 1;
   let isDefault = 1;
 }
 
@@ -173,4 +178,27 @@ def TDL_DirA : Directive<"dira"> {
 // GEN-NEXT:  }
 // GEN-EMPTY:
 // GEN-NEXT:  #endif // GEN_FLANG_DIRECTIVE_CLAUSE_MAP
+// GEN-EMPTY:
+// GEN-NEXT:  #ifdef GEN_FLANG_CLAUSE_PARSER_CLASSES
+// GEN-NEXT:  #undef GEN_FLANG_CLAUSE_PARSER_CLASSES
+// GEN-EMPTY:
+// GEN-NEXT:  WRAPPER_CLASS(Clauseb, std::optional<IntExpr>);
+// GEN-EMPTY:
+// GEN-NEXT:  #endif // GEN_FLANG_CLAUSE_PARSER_CLASSES
+// GEN-EMPTY:
+// GEN-NEXT:  #ifdef GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+// GEN-NEXT:  #undef GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+// GEN-EMPTY:
+// GEN-NEXT:  TdlClauseA
+// GEN-NEXT:  , Clauseb
+// GEN-EMPTY:
+// GEN-NEXT:  #endif // GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+// GEN-EMPTY:
+// GEN-NEXT:  #ifdef GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+// GEN-NEXT:  #undef GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+// GEN-EMPTY:
+// GEN-NEXT:  NODE(TdlClause, Clauseb)
+// GEN-EMPTY:
+// GEN-NEXT:  #endif // GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+
 

diff  --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td
index 02f9d4ec40e9..ed2ac7690841 100644
--- a/llvm/test/TableGen/directive2.td
+++ b/llvm/test/TableGen/directive2.td
@@ -11,6 +11,7 @@ def TestDirectiveLanguage : DirectiveLanguage {
   let directivePrefix = "TDLD_";
   let clausePrefix = "TDLC_";
   let includeHeader = "tdl.h.inc";
+  let flangClauseBaseClass = "TdlClause";
 }
 
 def TDLC_ClauseA : Clause<"clausea"> {
@@ -18,6 +19,7 @@ def TDLC_ClauseA : Clause<"clausea"> {
 }
 def TDLC_ClauseB : Clause<"clauseb"> {
   let isDefault = 1;
+  let flangClassValue = "IntExpr";
 }
 
 def TDL_DirA : Directive<"dira"> {
@@ -164,3 +166,28 @@ def TDL_DirA : Directive<"dira"> {
 // GEN-NEXT: }
 // GEN-EMPTY:
 // GEN-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_MAP
+// GEN-EMPTY:
+// GEN-NEXT:  #ifdef GEN_FLANG_CLAUSE_PARSER_CLASSES
+// GEN-NEXT:  #undef GEN_FLANG_CLAUSE_PARSER_CLASSES
+// GEN-EMPTY:
+// GEN-NEXT:  EMPTY_CLASS(Clausea);
+// GEN-NEXT:  WRAPPER_CLASS(Clauseb, IntExpr);
+// GEN-EMPTY:
+// GEN-NEXT:  #endif // GEN_FLANG_CLAUSE_PARSER_CLASSES
+// GEN-EMPTY:
+// GEN-NEXT:  #ifdef GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+// GEN-NEXT:  #undef GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+// GEN-EMPTY:
+// GEN-NEXT:  Clausea
+// GEN-NEXT:  , Clauseb
+// GEN-EMPTY:
+// GEN-NEXT:  #endif // GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST
+// GEN-EMPTY:
+// GEN-NEXT:  #ifdef GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+// GEN-NEXT:  #undef GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+// GEN-EMPTY:
+// GEN-NEXT:  NODE(TdlClause, Clausea)
+// GEN-NEXT:  NODE(TdlClause, Clauseb)
+// GEN-EMPTY:
+// GEN-NEXT:  #endif // GEN_FLANG_DUMP_PARSE_TREE_CLAUSES
+

diff  --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp
index 60c80eb09d73..ff35264f7c7b 100644
--- a/llvm/utils/TableGen/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/DirectiveEmitter.cpp
@@ -68,6 +68,10 @@ class DirectiveLanguage {
     return Def->getValueAsString("clauseEnumSetClass");
   }
 
+  StringRef getFlangClauseBaseClass() const {
+    return Def->getValueAsString("flangClauseBaseClass");
+  }
+
   bool hasMakeEnumAvailableInNamespace() const {
     return Def->getValueAsBit("makeEnumAvailableInNamespace");
   }
@@ -146,6 +150,35 @@ class Clause : public BaseRecord {
     return Def->getValueAsString("flangClass");
   }
 
+  // Optional field.
+  StringRef getFlangClassValue() const {
+    return Def->getValueAsString("flangClassValue");
+  }
+
+  // Get the formatted name for Flang parser class. The generic formatted class
+  // name is constructed from the name were the first letter of each word is
+  // captitalized and the underscores are removed.
+  // ex: async -> Async
+  //     num_threads -> NumThreads
+  std::string getFormattedParserClassName() {
+    StringRef Name = Def->getValueAsString("name");
+    std::string N = Name.str();
+    bool Cap = true;
+    std::transform(N.begin(), N.end(), N.begin(), [&Cap](unsigned char C) {
+      if (Cap == true) {
+        C = std::toupper(C);
+        Cap = false;
+      } else if (C == '_') {
+        Cap = true;
+      }
+      return C;
+    });
+    N.erase(std::remove(N.begin(), N.end(), '_'), N.end());
+    return N;
+  }
+
+  bool isValueOptional() const { return Def->getValueAsBit("isValueOptional"); }
+
   bool isImplict() const { return Def->getValueAsBit("isImplicit"); }
 };
 
@@ -489,15 +522,89 @@ void GenerateDirectiveClauseMap(const std::vector<Record *> &Directives,
   OS << "}\n";
 }
 
+// Generate classes entry for Flang clauses in the Flang parse-tree
+// If the clause as a non-generic class, no entry is generated.
+// If the clause does not hold a value, an EMPTY_CLASS is used.
+// If the clause class is generic then a WRAPPER_CLASS is used. When the value
+// is optional, the value class is wrapped into a std::optional.
+void GenerateFlangClauseParserClass(const std::vector<Record *> &Clauses,
+                                    raw_ostream &OS) {
+
+  IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES", OS);
+
+  OS << "\n";
+
+  for (const auto &C : Clauses) {
+    Clause Clause{C};
+    // Clause has a non generic class.
+    if (!Clause.getFlangClass().empty())
+      continue;
+    // G
+    if (!Clause.getFlangClassValue().empty()) {
+      if (Clause.isValueOptional()) {
+        OS << "WRAPPER_CLASS(" << Clause.getFormattedParserClassName()
+           << ", std::optional<" << Clause.getFlangClassValue() << ">);\n";
+      } else {
+        OS << "WRAPPER_CLASS(" << Clause.getFormattedParserClassName() << ", "
+           << Clause.getFlangClassValue() << ");\n";
+      }
+    } else {
+      OS << "EMPTY_CLASS(" << Clause.getFormattedParserClassName() << ");\n";
+    }
+  }
+}
+
+// Generate a list of the 
diff erent clause classes for Flang.
+void GenerateFlangClauseParserClassList(const std::vector<Record *> &Clauses,
+                                        raw_ostream &OS) {
+
+  IfDefScope Scope("GEN_FLANG_CLAUSE_PARSER_CLASSES_LIST", OS);
+
+  OS << "\n";
+  llvm::interleaveComma(Clauses, OS, [&](Record *C) {
+    Clause Clause{C};
+    if (Clause.getFlangClass().empty())
+      OS << Clause.getFormattedParserClassName() << "\n";
+    else
+      OS << Clause.getFlangClass() << "\n";
+  });
+}
+
+// Generate dump node list for the clauses holding a generic class name.
+void GenerateFlangClauseDump(const std::vector<Record *> &Clauses,
+                             const DirectiveLanguage &DirLang,
+                             raw_ostream &OS) {
+
+  IfDefScope Scope("GEN_FLANG_DUMP_PARSE_TREE_CLAUSES", OS);
+
+  OS << "\n";
+  for (const auto &C : Clauses) {
+    Clause Clause{C};
+    // Clause has a non generic class.
+    if (!Clause.getFlangClass().empty())
+      continue;
+
+    OS << "NODE(" << DirLang.getFlangClauseBaseClass() << ", "
+       << Clause.getFormattedParserClassName() << ")\n";
+  }
+}
+
 // Generate the implemenation section for the enumeration in the directive
 // language
 void EmitDirectivesFlangImpl(const std::vector<Record *> &Directives,
+                             const std::vector<Record *> &Clauses,
                              raw_ostream &OS,
                              DirectiveLanguage &DirectiveLanguage) {
 
   GenerateDirectiveClauseSets(Directives, OS, DirectiveLanguage);
 
   GenerateDirectiveClauseMap(Directives, OS, DirectiveLanguage);
+
+  GenerateFlangClauseParserClass(Clauses, OS);
+
+  GenerateFlangClauseParserClassList(Clauses, OS);
+
+  GenerateFlangClauseDump(Clauses, DirectiveLanguage, OS);
 }
 
 // Generate the implemenation section for the enumeration in the directive
@@ -513,8 +620,9 @@ void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) {
   }
 
   const auto &Directives = Records.getAllDerivedDefinitions("Directive");
+  const auto &Clauses = Records.getAllDerivedDefinitions("Clause");
   DirectiveLanguage DirectiveLanguage{DirectiveLanguages[0]};
-  EmitDirectivesFlangImpl(Directives, OS, DirectiveLanguage);
+  EmitDirectivesFlangImpl(Directives, Clauses, OS, DirectiveLanguage);
 }
 
 // Generate the implemenation for the enumeration in the directive


        


More information about the llvm-commits mailing list