[clang] 55120f7 - [Syntax] Add minimal TableGen for syntax nodes. NFC

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 9 14:46:46 PST 2020


Author: Sam McCall
Date: 2020-11-09T23:45:50+01:00
New Revision: 55120f74ca12faea0e90fe552c85c14485f1fd91

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

LOG: [Syntax] Add minimal TableGen for syntax nodes. NFC

So far, only used to generate Kind and implement classof().

My plan is to have this general-purpose Nodes.inc in the style of AST
DeclNodes.inc etc, and additionally a special-purpose backend generating
the actual class definitions. But baby steps...

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

Added: 
    clang/include/clang/Tooling/Syntax/CMakeLists.txt
    clang/include/clang/Tooling/Syntax/Nodes.td
    clang/include/clang/Tooling/Syntax/Syntax.td
    clang/utils/TableGen/ClangSyntaxEmitter.cpp

Modified: 
    clang/include/clang/CMakeLists.txt
    clang/include/clang/Tooling/Syntax/Nodes.h
    clang/lib/Tooling/Syntax/Nodes.cpp
    clang/lib/Tooling/Syntax/Tree.cpp
    clang/utils/TableGen/CMakeLists.txt
    clang/utils/TableGen/TableGen.cpp
    clang/utils/TableGen/TableGenBackends.h

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CMakeLists.txt b/clang/include/clang/CMakeLists.txt
index feb81f0686ca..0dc9ea5ed8ac 100644
--- a/clang/include/clang/CMakeLists.txt
+++ b/clang/include/clang/CMakeLists.txt
@@ -5,3 +5,4 @@ add_subdirectory(Parse)
 add_subdirectory(Sema)
 add_subdirectory(Serialization)
 add_subdirectory(StaticAnalyzer/Checkers)
+add_subdirectory(Tooling/Syntax)

diff  --git a/clang/include/clang/Tooling/Syntax/CMakeLists.txt b/clang/include/clang/Tooling/Syntax/CMakeLists.txt
new file mode 100644
index 000000000000..a740015de365
--- /dev/null
+++ b/clang/include/clang/Tooling/Syntax/CMakeLists.txt
@@ -0,0 +1,4 @@
+clang_tablegen(Nodes.inc -gen-clang-syntax-node-list
+  SOURCE Nodes.td
+  TARGET ClangSyntaxNodeList)
+

diff  --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h
index 33ed2ec5c349..ed170beb75c8 100644
--- a/clang/include/clang/Tooling/Syntax/Nodes.h
+++ b/clang/include/clang/Tooling/Syntax/Nodes.h
@@ -35,82 +35,8 @@ namespace syntax {
 /// blocks of enumerator constants must correspond to the inheritance hierarchy
 /// of syntax::Node.
 enum class NodeKind : uint16_t {
-  Leaf,
-  TranslationUnit,
-
-  // Expressions.
-  UnknownExpression,
-  PrefixUnaryOperatorExpression,
-  PostfixUnaryOperatorExpression,
-  BinaryOperatorExpression,
-  ParenExpression,
-  IntegerLiteralExpression,
-  CharacterLiteralExpression,
-  FloatingLiteralExpression,
-  StringLiteralExpression,
-  BoolLiteralExpression,
-  CxxNullPtrExpression,
-  IntegerUserDefinedLiteralExpression,
-  FloatUserDefinedLiteralExpression,
-  CharUserDefinedLiteralExpression,
-  StringUserDefinedLiteralExpression,
-  IdExpression,
-  MemberExpression,
-  ThisExpression,
-  CallExpression,
-
-  // Statements.
-  UnknownStatement,
-  DeclarationStatement,
-  EmptyStatement,
-  SwitchStatement,
-  CaseStatement,
-  DefaultStatement,
-  IfStatement,
-  ForStatement,
-  WhileStatement,
-  ContinueStatement,
-  BreakStatement,
-  ReturnStatement,
-  RangeBasedForStatement,
-  ExpressionStatement,
-  CompoundStatement,
-
-  // Declarations.
-  UnknownDeclaration,
-  EmptyDeclaration,
-  StaticAssertDeclaration,
-  LinkageSpecificationDeclaration,
-  SimpleDeclaration,
-  TemplateDeclaration,
-  ExplicitTemplateInstantiation,
-  NamespaceDefinition,
-  NamespaceAliasDefinition,
-  UsingNamespaceDirective,
-  UsingDeclaration,
-  TypeAliasDeclaration,
-
-  // Declarators.
-  SimpleDeclarator,
-  ParenDeclarator,
-
-  ArraySubscript,
-  TrailingReturnType,
-  ParametersAndQualifiers,
-  MemberPointer,
-  UnqualifiedId,
-
-  // Lists
-  DeclaratorList,
-  ParameterDeclarationList,
-  CallArguments,
-  NestedNameSpecifier,
-
-  // Name Specifiers.
-  GlobalNameSpecifier,
-  DecltypeNameSpecifier,
-  IdentifierNameSpecifier,
-  SimpleTemplateNameSpecifier,
+#define CONCRETE_NODE(Kind, Base) Kind,
+#include "clang/Tooling/Syntax/Nodes.inc"
 };
 /// For debugging purposes.
 raw_ostream &operator<<(raw_ostream &OS, NodeKind K);
@@ -194,9 +120,7 @@ class SimpleDeclarator;
 class TranslationUnit final : public Tree {
 public:
   TranslationUnit() : Tree(NodeKind::TranslationUnit) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::TranslationUnit;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A base class for all expressions. Note that expressions are not statements,
@@ -204,10 +128,7 @@ class TranslationUnit final : public Tree {
 class Expression : public Tree {
 public:
   Expression(NodeKind K) : Tree(K) {}
-  static bool classof(const Node *N) {
-    return NodeKind::UnknownExpression <= N->getKind() &&
-           N->getKind() <= NodeKind::CallExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A sequence of these specifiers make a `nested-name-specifier`.
@@ -215,12 +136,7 @@ class Expression : public Tree {
 class NameSpecifier : public Tree {
 public:
   NameSpecifier(NodeKind K) : Tree(K) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::GlobalNameSpecifier ||
-           N->getKind() == NodeKind::DecltypeNameSpecifier ||
-           N->getKind() == NodeKind::IdentifierNameSpecifier ||
-           N->getKind() == NodeKind::SimpleTemplateNameSpecifier;
-  }
+  static bool classof(const Node *N);
 };
 
 /// The global namespace name specifier, this specifier doesn't correspond to a
@@ -230,9 +146,7 @@ class NameSpecifier : public Tree {
 class GlobalNameSpecifier final : public NameSpecifier {
 public:
   GlobalNameSpecifier() : NameSpecifier(NodeKind::GlobalNameSpecifier) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::GlobalNameSpecifier;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A name specifier holding a decltype, of the form: `decltype ( expression ) `
@@ -240,9 +154,7 @@ class GlobalNameSpecifier final : public NameSpecifier {
 class DecltypeNameSpecifier final : public NameSpecifier {
 public:
   DecltypeNameSpecifier() : NameSpecifier(NodeKind::DecltypeNameSpecifier) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::DecltypeNameSpecifier;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A identifier name specifier, of the form `identifier`
@@ -251,9 +163,7 @@ class IdentifierNameSpecifier final : public NameSpecifier {
 public:
   IdentifierNameSpecifier()
       : NameSpecifier(NodeKind::IdentifierNameSpecifier) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::IdentifierNameSpecifier;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A name specifier with a simple-template-id, of the form `template_opt
@@ -263,9 +173,7 @@ class SimpleTemplateNameSpecifier final : public NameSpecifier {
 public:
   SimpleTemplateNameSpecifier()
       : NameSpecifier(NodeKind::SimpleTemplateNameSpecifier) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::SimpleTemplateNameSpecifier;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Models a `nested-name-specifier`. C++ [expr.prim.id.qual]
@@ -273,9 +181,7 @@ class SimpleTemplateNameSpecifier final : public NameSpecifier {
 class NestedNameSpecifier final : public List {
 public:
   NestedNameSpecifier() : List(NodeKind::NestedNameSpecifier) {}
-  static bool classof(const Node *N) {
-    return N->getKind() <= NodeKind::NestedNameSpecifier;
-  }
+  static bool classof(const Node *N);
   std::vector<NameSpecifier *> getSpecifiers();
   std::vector<List::ElementAndDelimiter<syntax::NameSpecifier>>
   getSpecifiersAndDoubleColons();
@@ -286,9 +192,7 @@ class NestedNameSpecifier final : public List {
 class UnqualifiedId final : public Tree {
 public:
   UnqualifiedId() : Tree(NodeKind::UnqualifiedId) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::UnqualifiedId;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Models an `id-expression`, e.g. `std::vector<int>::size`.
@@ -301,9 +205,7 @@ class UnqualifiedId final : public Tree {
 class IdExpression final : public Expression {
 public:
   IdExpression() : Expression(NodeKind::IdExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::IdExpression;
-  }
+  static bool classof(const Node *N);
   NestedNameSpecifier *getQualifier();
   Leaf *getTemplateKeyword();
   UnqualifiedId *getUnqualifiedId();
@@ -314,18 +216,14 @@ class IdExpression final : public Expression {
 class UnknownExpression final : public Expression {
 public:
   UnknownExpression() : Expression(NodeKind::UnknownExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::UnknownExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Models a this expression `this`. C++ [expr.prim.this]
 class ThisExpression final : public Expression {
 public:
   ThisExpression() : Expression(NodeKind::ThisExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ThisExpression;
-  }
+  static bool classof(const Node *N);
   Leaf *getThisKeyword();
 };
 
@@ -337,9 +235,7 @@ class ThisExpression final : public Expression {
 class CallArguments final : public List {
 public:
   CallArguments() : List(NodeKind::CallArguments) {}
-  static bool classof(const Node *N) {
-    return N->getKind() <= NodeKind::CallArguments;
-  }
+  static bool classof(const Node *N);
   std::vector<Expression *> getArguments();
   std::vector<List::ElementAndDelimiter<Expression>> getArgumentsAndCommas();
 };
@@ -351,9 +247,7 @@ class CallArguments final : public List {
 class CallExpression final : public Expression {
 public:
   CallExpression() : Expression(NodeKind::CallExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::CallExpression;
-  }
+  static bool classof(const Node *N);
   Expression *getCallee();
   Leaf *getOpenParen();
   CallArguments *getArguments();
@@ -365,9 +259,7 @@ class CallExpression final : public Expression {
 class ParenExpression final : public Expression {
 public:
   ParenExpression() : Expression(NodeKind::ParenExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ParenExpression;
-  }
+  static bool classof(const Node *N);
   Leaf *getOpenParen();
   Expression *getSubExpression();
   Leaf *getCloseParen();
@@ -384,9 +276,7 @@ class ParenExpression final : public Expression {
 class MemberExpression final : public Expression {
 public:
   MemberExpression() : Expression(NodeKind::MemberExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::MemberExpression;
-  }
+  static bool classof(const Node *N);
   Expression *getObject();
   Leaf *getAccessToken();
   Leaf *getTemplateKeyword();
@@ -397,18 +287,7 @@ class MemberExpression final : public Expression {
 class LiteralExpression : public Expression {
 public:
   LiteralExpression(NodeKind K) : Expression(K) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::IntegerLiteralExpression ||
-           N->getKind() == NodeKind::CharacterLiteralExpression ||
-           N->getKind() == NodeKind::FloatingLiteralExpression ||
-           N->getKind() == NodeKind::StringLiteralExpression ||
-           N->getKind() == NodeKind::BoolLiteralExpression ||
-           N->getKind() == NodeKind::CxxNullPtrExpression ||
-           N->getKind() == NodeKind::IntegerUserDefinedLiteralExpression ||
-           N->getKind() == NodeKind::FloatUserDefinedLiteralExpression ||
-           N->getKind() == NodeKind::CharUserDefinedLiteralExpression ||
-           N->getKind() == NodeKind::StringUserDefinedLiteralExpression;
-  }
+  static bool classof(const Node *N);
   Leaf *getLiteralToken();
 };
 
@@ -417,9 +296,7 @@ class IntegerLiteralExpression final : public LiteralExpression {
 public:
   IntegerLiteralExpression()
       : LiteralExpression(NodeKind::IntegerLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::IntegerLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for character literals. C++ [lex.ccon]
@@ -427,9 +304,7 @@ class CharacterLiteralExpression final : public LiteralExpression {
 public:
   CharacterLiteralExpression()
       : LiteralExpression(NodeKind::CharacterLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::CharacterLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for floating-point literals. C++ [lex.fcon]
@@ -437,9 +312,7 @@ class FloatingLiteralExpression final : public LiteralExpression {
 public:
   FloatingLiteralExpression()
       : LiteralExpression(NodeKind::FloatingLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::FloatingLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for string-literals. C++ [lex.string]
@@ -447,9 +320,7 @@ class StringLiteralExpression final : public LiteralExpression {
 public:
   StringLiteralExpression()
       : LiteralExpression(NodeKind::StringLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::StringLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for boolean literals. C++ [lex.bool]
@@ -457,18 +328,14 @@ class BoolLiteralExpression final : public LiteralExpression {
 public:
   BoolLiteralExpression()
       : LiteralExpression(NodeKind::BoolLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::BoolLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for the `nullptr` literal. C++ [lex.nullptr]
 class CxxNullPtrExpression final : public LiteralExpression {
 public:
   CxxNullPtrExpression() : LiteralExpression(NodeKind::CxxNullPtrExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::CxxNullPtrExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for user-defined literal. C++ [lex.ext]
@@ -480,12 +347,7 @@ class CxxNullPtrExpression final : public LiteralExpression {
 class UserDefinedLiteralExpression : public LiteralExpression {
 public:
   UserDefinedLiteralExpression(NodeKind K) : LiteralExpression(K) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::IntegerUserDefinedLiteralExpression ||
-           N->getKind() == NodeKind::FloatUserDefinedLiteralExpression ||
-           N->getKind() == NodeKind::CharUserDefinedLiteralExpression ||
-           N->getKind() == NodeKind::StringUserDefinedLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for user-defined-integer-literal. C++ [lex.ext]
@@ -495,9 +357,7 @@ class IntegerUserDefinedLiteralExpression final
   IntegerUserDefinedLiteralExpression()
       : UserDefinedLiteralExpression(
             NodeKind::IntegerUserDefinedLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::IntegerUserDefinedLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for user-defined-floating-point-literal. C++ [lex.ext]
@@ -507,9 +367,7 @@ class FloatUserDefinedLiteralExpression final
   FloatUserDefinedLiteralExpression()
       : UserDefinedLiteralExpression(
             NodeKind::FloatUserDefinedLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::FloatUserDefinedLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for user-defined-character-literal. C++ [lex.ext]
@@ -519,9 +377,7 @@ class CharUserDefinedLiteralExpression final
   CharUserDefinedLiteralExpression()
       : UserDefinedLiteralExpression(
             NodeKind::CharUserDefinedLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::CharUserDefinedLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Expression for user-defined-string-literal. C++ [lex.ext]
@@ -531,19 +387,14 @@ class StringUserDefinedLiteralExpression final
   StringUserDefinedLiteralExpression()
       : UserDefinedLiteralExpression(
             NodeKind::StringUserDefinedLiteralExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::StringUserDefinedLiteralExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// An abstract class for prefix and postfix unary operators.
 class UnaryOperatorExpression : public Expression {
 public:
   UnaryOperatorExpression(NodeKind K) : Expression(K) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::PrefixUnaryOperatorExpression ||
-           N->getKind() == NodeKind::PostfixUnaryOperatorExpression;
-  }
+  static bool classof(const Node *N);
   Leaf *getOperatorToken();
   Expression *getOperand();
 };
@@ -561,9 +412,7 @@ class PrefixUnaryOperatorExpression final : public UnaryOperatorExpression {
 public:
   PrefixUnaryOperatorExpression()
       : UnaryOperatorExpression(NodeKind::PrefixUnaryOperatorExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::PrefixUnaryOperatorExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// <operand> <operator>
@@ -575,9 +424,7 @@ class PostfixUnaryOperatorExpression final : public UnaryOperatorExpression {
 public:
   PostfixUnaryOperatorExpression()
       : UnaryOperatorExpression(NodeKind::PostfixUnaryOperatorExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::PostfixUnaryOperatorExpression;
-  }
+  static bool classof(const Node *N);
 };
 
 /// <lhs> <operator> <rhs>
@@ -590,9 +437,7 @@ class PostfixUnaryOperatorExpression final : public UnaryOperatorExpression {
 class BinaryOperatorExpression final : public Expression {
 public:
   BinaryOperatorExpression() : Expression(NodeKind::BinaryOperatorExpression) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::BinaryOperatorExpression;
-  }
+  static bool classof(const Node *N);
   Expression *getLhs();
   Leaf *getOperatorToken();
   Expression *getRhs();
@@ -603,10 +448,7 @@ class BinaryOperatorExpression final : public Expression {
 class Statement : public Tree {
 public:
   Statement(NodeKind K) : Tree(K) {}
-  static bool classof(const Node *N) {
-    return NodeKind::UnknownStatement <= N->getKind() &&
-           N->getKind() <= NodeKind::CompoundStatement;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A statement of an unknown kind, i.e. one not currently handled by the syntax
@@ -614,36 +456,28 @@ class Statement : public Tree {
 class UnknownStatement final : public Statement {
 public:
   UnknownStatement() : Statement(NodeKind::UnknownStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::UnknownStatement;
-  }
+  static bool classof(const Node *N);
 };
 
 /// E.g. 'int a, b = 10;'
 class DeclarationStatement final : public Statement {
 public:
   DeclarationStatement() : Statement(NodeKind::DeclarationStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::DeclarationStatement;
-  }
+  static bool classof(const Node *N);
 };
 
 /// The no-op statement, i.e. ';'.
 class EmptyStatement final : public Statement {
 public:
   EmptyStatement() : Statement(NodeKind::EmptyStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::EmptyStatement;
-  }
+  static bool classof(const Node *N);
 };
 
 /// switch (<cond>) <body>
 class SwitchStatement final : public Statement {
 public:
   SwitchStatement() : Statement(NodeKind::SwitchStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::SwitchStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getSwitchKeyword();
   Statement *getBody();
 };
@@ -652,9 +486,7 @@ class SwitchStatement final : public Statement {
 class CaseStatement final : public Statement {
 public:
   CaseStatement() : Statement(NodeKind::CaseStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::CaseStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getCaseKeyword();
   Expression *getCaseValue();
   Statement *getBody();
@@ -664,9 +496,7 @@ class CaseStatement final : public Statement {
 class DefaultStatement final : public Statement {
 public:
   DefaultStatement() : Statement(NodeKind::DefaultStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::DefaultStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getDefaultKeyword();
   Statement *getBody();
 };
@@ -676,9 +506,7 @@ class DefaultStatement final : public Statement {
 class IfStatement final : public Statement {
 public:
   IfStatement() : Statement(NodeKind::IfStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::IfStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getIfKeyword();
   Statement *getThenStatement();
   Leaf *getElseKeyword();
@@ -689,9 +517,7 @@ class IfStatement final : public Statement {
 class ForStatement final : public Statement {
 public:
   ForStatement() : Statement(NodeKind::ForStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ForStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getForKeyword();
   Statement *getBody();
 };
@@ -700,9 +526,7 @@ class ForStatement final : public Statement {
 class WhileStatement final : public Statement {
 public:
   WhileStatement() : Statement(NodeKind::WhileStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::WhileStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getWhileKeyword();
   Statement *getBody();
 };
@@ -711,9 +535,7 @@ class WhileStatement final : public Statement {
 class ContinueStatement final : public Statement {
 public:
   ContinueStatement() : Statement(NodeKind::ContinueStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ContinueStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getContinueKeyword();
 };
 
@@ -721,9 +543,7 @@ class ContinueStatement final : public Statement {
 class BreakStatement final : public Statement {
 public:
   BreakStatement() : Statement(NodeKind::BreakStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::BreakStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getBreakKeyword();
 };
 
@@ -732,9 +552,7 @@ class BreakStatement final : public Statement {
 class ReturnStatement final : public Statement {
 public:
   ReturnStatement() : Statement(NodeKind::ReturnStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ReturnStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getReturnKeyword();
   Expression *getReturnValue();
 };
@@ -743,9 +561,7 @@ class ReturnStatement final : public Statement {
 class RangeBasedForStatement final : public Statement {
 public:
   RangeBasedForStatement() : Statement(NodeKind::RangeBasedForStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::RangeBasedForStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getForKeyword();
   Statement *getBody();
 };
@@ -755,9 +571,7 @@ class RangeBasedForStatement final : public Statement {
 class ExpressionStatement final : public Statement {
 public:
   ExpressionStatement() : Statement(NodeKind::ExpressionStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ExpressionStatement;
-  }
+  static bool classof(const Node *N);
   Expression *getExpression();
 };
 
@@ -765,9 +579,7 @@ class ExpressionStatement final : public Statement {
 class CompoundStatement final : public Statement {
 public:
   CompoundStatement() : Statement(NodeKind::CompoundStatement) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::CompoundStatement;
-  }
+  static bool classof(const Node *N);
   Leaf *getLbrace();
   /// FIXME: use custom iterator instead of 'vector'.
   std::vector<Statement *> getStatements();
@@ -781,28 +593,21 @@ class CompoundStatement final : public Statement {
 class Declaration : public Tree {
 public:
   Declaration(NodeKind K) : Tree(K) {}
-  static bool classof(const Node *N) {
-    return NodeKind::UnknownDeclaration <= N->getKind() &&
-           N->getKind() <= NodeKind::TypeAliasDeclaration;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Declaration of an unknown kind, e.g. not yet supported in syntax trees.
 class UnknownDeclaration final : public Declaration {
 public:
   UnknownDeclaration() : Declaration(NodeKind::UnknownDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::UnknownDeclaration;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A semicolon in the top-level context. Does not declare anything.
 class EmptyDeclaration final : public Declaration {
 public:
   EmptyDeclaration() : Declaration(NodeKind::EmptyDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::EmptyDeclaration;
-  }
+  static bool classof(const Node *N);
 };
 
 /// static_assert(<condition>, <message>)
@@ -810,9 +615,7 @@ class EmptyDeclaration final : public Declaration {
 class StaticAssertDeclaration final : public Declaration {
 public:
   StaticAssertDeclaration() : Declaration(NodeKind::StaticAssertDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::StaticAssertDeclaration;
-  }
+  static bool classof(const Node *N);
   Expression *getCondition();
   Expression *getMessage();
 };
@@ -823,17 +626,13 @@ class LinkageSpecificationDeclaration final : public Declaration {
 public:
   LinkageSpecificationDeclaration()
       : Declaration(NodeKind::LinkageSpecificationDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::LinkageSpecificationDeclaration;
-  }
+  static bool classof(const Node *N);
 };
 
 class DeclaratorList final : public List {
 public:
   DeclaratorList() : List(NodeKind::DeclaratorList) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::DeclaratorList;
-  }
+  static bool classof(const Node *N);
   std::vector<SimpleDeclarator *> getDeclarators();
   std::vector<List::ElementAndDelimiter<syntax::SimpleDeclarator>>
   getDeclaratorsAndCommas();
@@ -845,9 +644,7 @@ class DeclaratorList final : public List {
 class SimpleDeclaration final : public Declaration {
 public:
   SimpleDeclaration() : Declaration(NodeKind::SimpleDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::SimpleDeclaration;
-  }
+  static bool classof(const Node *N);
   /// FIXME: use custom iterator instead of 'vector'.
   std::vector<SimpleDeclarator *> getDeclarators();
 };
@@ -856,9 +653,7 @@ class SimpleDeclaration final : public Declaration {
 class TemplateDeclaration final : public Declaration {
 public:
   TemplateDeclaration() : Declaration(NodeKind::TemplateDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::TemplateDeclaration;
-  }
+  static bool classof(const Node *N);
   Leaf *getTemplateKeyword();
   Declaration *getDeclaration();
 };
@@ -872,9 +667,7 @@ class ExplicitTemplateInstantiation final : public Declaration {
 public:
   ExplicitTemplateInstantiation()
       : Declaration(NodeKind::ExplicitTemplateInstantiation) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ExplicitTemplateInstantiation;
-  }
+  static bool classof(const Node *N);
   Leaf *getTemplateKeyword();
   Leaf *getExternKeyword();
   Declaration *getDeclaration();
@@ -884,9 +677,7 @@ class ExplicitTemplateInstantiation final : public Declaration {
 class NamespaceDefinition final : public Declaration {
 public:
   NamespaceDefinition() : Declaration(NodeKind::NamespaceDefinition) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::NamespaceDefinition;
-  }
+  static bool classof(const Node *N);
 };
 
 /// namespace <name> = <namespace-reference>
@@ -894,18 +685,14 @@ class NamespaceAliasDefinition final : public Declaration {
 public:
   NamespaceAliasDefinition()
       : Declaration(NodeKind::NamespaceAliasDefinition) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::NamespaceAliasDefinition;
-  }
+  static bool classof(const Node *N);
 };
 
 /// using namespace <name>
 class UsingNamespaceDirective final : public Declaration {
 public:
   UsingNamespaceDirective() : Declaration(NodeKind::UsingNamespaceDirective) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::UsingNamespaceDirective;
-  }
+  static bool classof(const Node *N);
 };
 
 /// using <scope>::<name>
@@ -913,18 +700,14 @@ class UsingNamespaceDirective final : public Declaration {
 class UsingDeclaration final : public Declaration {
 public:
   UsingDeclaration() : Declaration(NodeKind::UsingDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::UsingDeclaration;
-  }
+  static bool classof(const Node *N);
 };
 
 /// using <name> = <type>
 class TypeAliasDeclaration final : public Declaration {
 public:
   TypeAliasDeclaration() : Declaration(NodeKind::TypeAliasDeclaration) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::TypeAliasDeclaration;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Covers a name, an initializer and a part of the type outside declaration
@@ -942,10 +725,7 @@ class TypeAliasDeclaration final : public Declaration {
 class Declarator : public Tree {
 public:
   Declarator(NodeKind K) : Tree(K) {}
-  static bool classof(const Node *N) {
-    return NodeKind::SimpleDeclarator <= N->getKind() &&
-           N->getKind() <= NodeKind::ParenDeclarator;
-  }
+  static bool classof(const Node *N);
 };
 
 /// A top-level declarator without parentheses. See comment of Declarator for
@@ -953,9 +733,7 @@ class Declarator : public Tree {
 class SimpleDeclarator final : public Declarator {
 public:
   SimpleDeclarator() : Declarator(NodeKind::SimpleDeclarator) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::SimpleDeclarator;
-  }
+  static bool classof(const Node *N);
 };
 
 /// Declarator inside parentheses.
@@ -964,9 +742,7 @@ class SimpleDeclarator final : public Declarator {
 class ParenDeclarator final : public Declarator {
 public:
   ParenDeclarator() : Declarator(NodeKind::ParenDeclarator) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ParenDeclarator;
-  }
+  static bool classof(const Node *N);
   Leaf *getLparen();
   Leaf *getRparen();
 };
@@ -978,9 +754,7 @@ class ParenDeclarator final : public Declarator {
 class ArraySubscript final : public Tree {
 public:
   ArraySubscript() : Tree(NodeKind::ArraySubscript) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ArraySubscript;
-  }
+  static bool classof(const Node *N);
   // TODO: add an accessor for the "static" keyword.
   Leaf *getLbracket();
   Expression *getSize();
@@ -992,9 +766,7 @@ class ArraySubscript final : public Tree {
 class TrailingReturnType final : public Tree {
 public:
   TrailingReturnType() : Tree(NodeKind::TrailingReturnType) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::TrailingReturnType;
-  }
+  static bool classof(const Node *N);
   // TODO: add accessors for specifiers.
   Leaf *getArrowToken();
   // FIXME: This should be a `type-id` following the grammar. Fix this once we
@@ -1007,9 +779,7 @@ class TrailingReturnType final : public Tree {
 class ParameterDeclarationList final : public List {
 public:
   ParameterDeclarationList() : List(NodeKind::ParameterDeclarationList) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ParameterDeclarationList;
-  }
+  static bool classof(const Node *N);
   std::vector<SimpleDeclaration *> getParameterDeclarations();
   std::vector<List::ElementAndDelimiter<syntax::SimpleDeclaration>>
   getParametersAndCommas();
@@ -1029,9 +799,7 @@ class ParameterDeclarationList final : public List {
 class ParametersAndQualifiers final : public Tree {
 public:
   ParametersAndQualifiers() : Tree(NodeKind::ParametersAndQualifiers) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::ParametersAndQualifiers;
-  }
+  static bool classof(const Node *N);
   Leaf *getLparen();
   ParameterDeclarationList *getParameters();
   Leaf *getRparen();
@@ -1043,11 +811,19 @@ class ParametersAndQualifiers final : public Tree {
 class MemberPointer final : public Tree {
 public:
   MemberPointer() : Tree(NodeKind::MemberPointer) {}
-  static bool classof(const Node *N) {
-    return N->getKind() == NodeKind::MemberPointer;
-  }
+  static bool classof(const Node *N);
 };
 
+#define CONCRETE_NODE(Kind, Base)                                              \
+  inline bool Kind::classof(const Node *N) {                                   \
+    return N->getKind() == NodeKind::Kind;                                     \
+  }
+#define ABSTRACT_NODE(Kind, Base, First, Last)                                 \
+  inline bool Kind::classof(const Node *N) {                                   \
+    return N->getKind() >= NodeKind::First && N->getKind() <= NodeKind::Last;  \
+  }
+#include "clang/Tooling/Syntax/Nodes.inc"
+
 } // namespace syntax
 } // namespace clang
 #endif

diff  --git a/clang/include/clang/Tooling/Syntax/Nodes.td b/clang/include/clang/Tooling/Syntax/Nodes.td
new file mode 100644
index 000000000000..bd12457df3c2
--- /dev/null
+++ b/clang/include/clang/Tooling/Syntax/Nodes.td
@@ -0,0 +1,106 @@
+//===- Nodes.td - Node types in the Syntax Tree grammar -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines concrete nodes in the syntax tree.
+// The archetypes they fall into (Sequence, List etc) are defined in Syntax.td.
+//
+// The C++ classes for the archetypes themselves are written by hand, and the
+// concrete node classes will be generated. Migration to TableGen is not
+// complete, so currently there is a mix of generated and hand-authored code.
+//
+//===----------------------------------------------------------------------===//
+
+include "clang/Tooling/Syntax/Syntax.td"
+
+def Node : External<?> {}
+def Leaf : External<Node> {}
+def Tree : External<Node> {}
+
+def TranslationUnit : External<Tree> {}
+
+def Expression : External<Tree> {}
+def UnknownExpression : External<Expression> {}
+def UnaryOperatorExpression : External<Tree> {}
+def PrefixUnaryOperatorExpression : External<UnaryOperatorExpression> {}
+def PostfixUnaryOperatorExpression : External<UnaryOperatorExpression> {}
+def BinaryOperatorExpression : External<Expression> {}
+def ParenExpression : External<Expression> {}
+def LiteralExpression : External<Expression> {}
+def IntegerLiteralExpression : External<LiteralExpression> {}
+def CharacterLiteralExpression : External<LiteralExpression> {}
+def FloatingLiteralExpression : External<LiteralExpression> {}
+def StringLiteralExpression : External<LiteralExpression> {}
+def BoolLiteralExpression : External<LiteralExpression> {}
+def CxxNullPtrExpression : External<LiteralExpression> {}
+def UserDefinedLiteralExpression : External<LiteralExpression> {}
+def IntegerUserDefinedLiteralExpression : External<UserDefinedLiteralExpression> {}
+def FloatUserDefinedLiteralExpression : External<UserDefinedLiteralExpression> {}
+def CharUserDefinedLiteralExpression : External<UserDefinedLiteralExpression> {}
+def StringUserDefinedLiteralExpression : External<UserDefinedLiteralExpression> {}
+def IdExpression : External<Expression> {}
+def MemberExpression : External<Expression> {}
+def ThisExpression : External<Expression> {}
+def CallExpression : External<Expression> {}
+
+// Statements.
+def Statement : External<Tree> {}
+def UnknownStatement : External<Statement> {}
+def DeclarationStatement : External<Statement> {}
+def EmptyStatement : External<Statement> {}
+def SwitchStatement : External<Statement> {}
+def CaseStatement : External<Statement> {}
+def DefaultStatement : External<Statement> {}
+def IfStatement : External<Statement> {}
+def ForStatement : External<Statement> {}
+def WhileStatement : External<Statement> {}
+def ContinueStatement : External<Statement> {}
+def BreakStatement : External<Statement> {}
+def ReturnStatement : External<Statement> {}
+def RangeBasedForStatement : External<Statement> {}
+def ExpressionStatement : External<Statement> {}
+def CompoundStatement : External<Statement> {}
+
+// Declarations.
+def Declaration : External<Tree> {}
+def UnknownDeclaration : External<Declaration> {}
+def EmptyDeclaration : External<Declaration> {}
+def StaticAssertDeclaration : External<Declaration> {}
+def LinkageSpecificationDeclaration : External<Declaration> {}
+def SimpleDeclaration : External<Declaration> {}
+def TemplateDeclaration : External<Declaration> {}
+def ExplicitTemplateInstantiation : External<Declaration> {}
+def NamespaceDefinition : External<Declaration> {}
+def NamespaceAliasDefinition : External<Declaration> {}
+def UsingNamespaceDirective : External<Declaration> {}
+def UsingDeclaration : External<Declaration> {}
+def TypeAliasDeclaration : External<Declaration> {}
+
+// Declarators.
+def Declarator : External<Tree> {}
+def SimpleDeclarator : External<Declarator> {}
+def ParenDeclarator : External<Declarator> {}
+
+def ArraySubscript : External<Tree> {}
+def TrailingReturnType : External<Tree> {}
+def ParametersAndQualifiers : External<Tree> {}
+def MemberPointer : External<Tree> {}
+def UnqualifiedId : External<Tree> {}
+
+// Lists
+def List : External<Tree> {}
+def DeclaratorList : External<List> {}
+def ParameterDeclarationList : External<List> {}
+def CallArguments : External<List> {}
+def NestedNameSpecifier : External<List> {}
+
+// Name Specifiers.
+def NameSpecifier : External<Tree> {}
+def GlobalNameSpecifier : External<NameSpecifier> {}
+def DecltypeNameSpecifier : External<NameSpecifier> {}
+def IdentifierNameSpecifier : External<NameSpecifier> {}
+def SimpleTemplateNameSpecifier : External<NameSpecifier> {}

diff  --git a/clang/include/clang/Tooling/Syntax/Syntax.td b/clang/include/clang/Tooling/Syntax/Syntax.td
new file mode 100644
index 000000000000..2e1d69190e42
--- /dev/null
+++ b/clang/include/clang/Tooling/Syntax/Syntax.td
@@ -0,0 +1,40 @@
+//===- Syntax.td - TableGen metamodel for syntax::Node hierarchy ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The tree representation of the is C++ syntax is quite regular.
+//
+// There are 4 archetypes of nodes in the syntax tree:
+//  - Leaves, owning exactly one token. (syntax::Leaf)
+//  - Sequences, with a fixed list of children that should appear in order.
+//    The concrete node defines a Role sequence which identifies the children.
+//    The type of child in each role is also constrained.
+//  - Lists, with children in alternating Element/Delimiter roles. (syntax::List)
+//    The concrete node defines the element type, delimiters are always leaves.
+//  - Alternatives, where several 
diff erent node types are allowed.
+//    These are modeled as abstract types with inheritance (e.g. Declaration).
+//
+// This file defines TableGen classes modelling these archetypes.
+// The concrete nodes are defined in terms of these classes in Nodes.td.
+//
+// The C++ classes for the archetypes themselves are written by hand, and the
+// concrete node classes will be generated. Migration to TableGen is not
+// complete, so currently there is a mix of generated and hand-authored code.
+//
+//===----------------------------------------------------------------------===//
+
+// Defs derived from NodeType correspond to syntax tree node types.
+class NodeType {
+  // The NodeType that this node is derived from in the Node class hierarchy.
+  NodeType base = ?;
+}
+
+// A node type which is defined in Nodes.h rather than by generated code.
+// We merely specify the inheritance hierarchy here.
+class External<NodeType base_> : NodeType { let base = base_; }
+
+// FIXME: add sequence, list, and alternative archetypes.

diff  --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp
index b4d1cfd75ac5..0be9f1f03add 100644
--- a/clang/lib/Tooling/Syntax/Nodes.cpp
+++ b/clang/lib/Tooling/Syntax/Nodes.cpp
@@ -630,3 +630,7 @@ syntax::ParametersAndQualifiers::getTrailingReturn() {
   return cast_or_null<syntax::TrailingReturnType>(
       findChild(syntax::NodeRole::TrailingReturn));
 }
+
+#define NODE(Kind, Parent)                                                     \
+  static_assert(sizeof(syntax::Kind) > 0, "Missing Node subclass definition");
+#include "clang/Tooling/Syntax/Nodes.inc"

diff  --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp
index fca2be5361cf..07ee13e313f5 100644
--- a/clang/lib/Tooling/Syntax/Tree.cpp
+++ b/clang/lib/Tooling/Syntax/Tree.cpp
@@ -52,10 +52,6 @@ syntax::Leaf::Leaf(const syntax::Token *Tok) : Node(NodeKind::Leaf), Tok(Tok) {
   assert(Tok != nullptr);
 }
 
-bool syntax::Leaf::classof(const Node *N) {
-  return N->getKind() == NodeKind::Leaf;
-}
-
 syntax::Node::Node(NodeKind Kind)
     : Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
       Kind(static_cast<unsigned>(Kind)), Role(0), Original(false),
@@ -71,10 +67,6 @@ void syntax::Node::setRole(NodeRole NR) {
   this->Role = static_cast<unsigned>(NR);
 }
 
-bool syntax::Tree::classof(const Node *N) {
-  return N->getKind() > NodeKind::Leaf;
-}
-
 void syntax::Tree::appendChildLowLevel(Node *Child, NodeRole Role) {
   assert(Child->getRole() == NodeRole::Detached);
   assert(Role != NodeRole::Detached);
@@ -345,18 +337,6 @@ const syntax::Node *syntax::Tree::findChild(NodeRole R) const {
   return nullptr;
 }
 
-bool syntax::List::classof(const syntax::Node *N) {
-  switch (N->getKind()) {
-  case syntax::NodeKind::NestedNameSpecifier:
-  case syntax::NodeKind::CallArguments:
-  case syntax::NodeKind::ParameterDeclarationList:
-  case syntax::NodeKind::DeclaratorList:
-    return true;
-  default:
-    return false;
-  }
-}
-
 std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
 syntax::List::getElementsAsNodesAndDelimiters() {
   if (!getFirstChild())

diff  --git a/clang/utils/TableGen/CMakeLists.txt b/clang/utils/TableGen/CMakeLists.txt
index 41f15e2d7909..26589ec7e1ce 100644
--- a/clang/utils/TableGen/CMakeLists.txt
+++ b/clang/utils/TableGen/CMakeLists.txt
@@ -14,6 +14,7 @@ add_tablegen(clang-tblgen CLANG
   ClangOpenCLBuiltinEmitter.cpp
   ClangOptionDocEmitter.cpp
   ClangSACheckersEmitter.cpp
+  ClangSyntaxEmitter.cpp
   ClangTypeNodesEmitter.cpp
   MveEmitter.cpp
   NeonEmitter.cpp

diff  --git a/clang/utils/TableGen/ClangSyntaxEmitter.cpp b/clang/utils/TableGen/ClangSyntaxEmitter.cpp
new file mode 100644
index 000000000000..d5ef7c97c084
--- /dev/null
+++ b/clang/utils/TableGen/ClangSyntaxEmitter.cpp
@@ -0,0 +1,129 @@
+//===- ClangSyntaxEmitter.cpp - Generate clang Syntax Tree nodes ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// These backends consume the definitions of Syntax Tree nodes.
+// See clang/include/clang/Tooling/Syntax/{Syntax,Nodes}.td
+//
+// The -gen-clang-syntax-node-list backend produces a .inc with macro calls
+//   NODE(Kind, BaseKind)
+//   ABSTRACT_NODE(Type, Base, FirstKind, LastKind)
+// similar to those for AST nodes such as AST/DeclNodes.inc.
+//
+// In future, the class definitions will be produced by additional backends.
+//
+//===----------------------------------------------------------------------===//
+#include "TableGenBackends.h"
+
+#include <deque>
+
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+namespace {
+
+// The class hierarchy of Node types.
+// We assemble this in order to be able to define the NodeKind enum in a
+// stable and useful way, where abstract Node subclasses correspond to ranges.
+class Hierarchy {
+public:
+  Hierarchy(const llvm::RecordKeeper &Records) {
+    for (llvm::Record *T : Records.getAllDerivedDefinitions("NodeType"))
+      add(T);
+    for (llvm::Record *Derived : Records.getAllDerivedDefinitions("NodeType"))
+      if (llvm::Record *Base = Derived->getValueAsOptionalDef("base"))
+        link(Derived, Base);
+    for (NodeType &N : AllTypes)
+      llvm::sort(N.Derived, [](const NodeType *L, const NodeType *R) {
+        return L->Record->getName() < R->Record->getName();
+      });
+  }
+
+  struct NodeType {
+    const llvm::Record *Record = nullptr;
+    const NodeType *Base = nullptr;
+    std::vector<const NodeType *> Derived;
+    llvm::StringRef name() const { return Record->getName(); }
+  };
+
+  NodeType &get(llvm::StringRef Name = "Node") {
+    auto NI = ByName.find(Name);
+    assert(NI != ByName.end() && "no such node");
+    return *NI->second;
+  }
+
+private:
+  void add(const llvm::Record *R) {
+    AllTypes.emplace_back();
+    AllTypes.back().Record = R;
+    assert(ByName.try_emplace(R->getName(), &AllTypes.back()).second &&
+           "Duplicate node name");
+  }
+
+  void link(const llvm::Record *Derived, const llvm::Record *Base) {
+    auto &CN = get(Derived->getName()), &PN = get(Base->getName());
+    assert(CN.Base == nullptr && "setting base twice");
+    PN.Derived.push_back(&CN);
+    CN.Base = &PN;
+  }
+
+  std::deque<NodeType> AllTypes;
+  llvm::DenseMap<llvm::StringRef, NodeType *> ByName;
+};
+
+const Hierarchy::NodeType &firstConcrete(const Hierarchy::NodeType &N) {
+  return N.Derived.empty() ? N : firstConcrete(*N.Derived.front());
+}
+const Hierarchy::NodeType &lastConcrete(const Hierarchy::NodeType &N) {
+  return N.Derived.empty() ? N : lastConcrete(*N.Derived.back());
+}
+
+void emitNodeList(const Hierarchy::NodeType &N, llvm::raw_ostream &OS) {
+  // Don't emit ABSTRACT_NODE for node itself, which has no parent.
+  if (N.Base != nullptr) {
+    if (N.Derived.empty())
+      OS << llvm::formatv("CONCRETE_NODE({0},{1})\n", N.name(), N.Base->name());
+    else
+      OS << llvm::formatv("ABSTRACT_NODE({0},{1},{2},{3})\n", N.name(),
+                          N.Base->name(), firstConcrete(N).name(),
+                          lastConcrete(N).name());
+  }
+  for (const auto *C : N.Derived)
+    emitNodeList(*C, OS);
+}
+
+} // namespace
+
+void clang::EmitClangSyntaxNodeList(llvm::RecordKeeper &Records,
+                                    llvm::raw_ostream &OS) {
+  llvm::emitSourceFileHeader("Syntax tree node list", OS);
+  OS << "// Generated from " << Records.getInputFilename() << "\n";
+  OS << R"cpp(
+#ifndef NODE
+#define NODE(Kind, Base)
+#endif
+
+#ifndef CONCRETE_NODE
+#define CONCRETE_NODE(Kind, Base) NODE(Kind, Base)
+#endif
+
+#ifndef ABSTRACT_NODE
+#define ABSTRACT_NODE(Kind, Base, First, Last) NODE(Kind, Base)
+#endif
+
+)cpp";
+  emitNodeList(Hierarchy(Records).get(), OS);
+  OS << R"cpp(
+#undef NODE
+#undef CONCRETE_NODE
+#undef ABSTRACT_NODE
+)cpp";
+}

diff  --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 1d6ef8065bb8..12d4ba6d47d1 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -55,6 +55,7 @@ enum ActionType {
   GenClangTypeWriter,
   GenClangOpcodes,
   GenClangSACheckers,
+  GenClangSyntaxNodeList,
   GenClangCommentHTMLTags,
   GenClangCommentHTMLTagsProperties,
   GenClangCommentHTMLNamedCharacterReferences,
@@ -166,6 +167,8 @@ cl::opt<ActionType> Action(
                    "Generate Clang constexpr interpreter opcodes"),
         clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
                    "Generate Clang Static Analyzer checkers"),
+        clEnumValN(GenClangSyntaxNodeList, "gen-clang-syntax-node-list",
+                   "Generate list of Clang Syntax Tree node types"),
         clEnumValN(GenClangCommentHTMLTags, "gen-clang-comment-html-tags",
                    "Generate efficient matchers for HTML tag "
                    "names that are used in documentation comments"),
@@ -356,6 +359,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
   case GenClangOpenCLBuiltins:
     EmitClangOpenCLBuiltins(Records, OS);
     break;
+  case GenClangSyntaxNodeList:
+    EmitClangSyntaxNodeList(Records, OS);
+    break;
   case GenArmNeon:
     EmitNeon(Records, OS);
     break;

diff  --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index 9717903ba52c..47e552327cb1 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -83,6 +83,9 @@ void EmitClangCommentCommandList(llvm::RecordKeeper &Records,
                                  llvm::raw_ostream &OS);
 void EmitClangOpcodes(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 
+void EmitClangSyntaxNodeList(llvm::RecordKeeper &Records,
+                             llvm::raw_ostream &OS);
+
 void EmitNeon(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitFP16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
 void EmitBF16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);


        


More information about the cfe-commits mailing list