Reland [Syntax] Add minimal TableGen for syntax nodes. NFC

This reverts commit 09c6259d6d.
(Fixed side-effecting code being buried in an assert)
This commit is contained in:
Sam McCall 2020-11-10 00:00:51 +01:00
parent e7b8d3776f
commit 454579e46a
11 changed files with 377 additions and 326 deletions

View File

@ -5,3 +5,4 @@ add_subdirectory(Parse)
add_subdirectory(Sema)
add_subdirectory(Serialization)
add_subdirectory(StaticAnalyzer/Checkers)
add_subdirectory(Tooling/Syntax)

View File

@ -0,0 +1,4 @@
clang_tablegen(Nodes.inc -gen-clang-syntax-node-list
SOURCE Nodes.td
TARGET ClangSyntaxNodeList)

View File

@ -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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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

View File

@ -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> {}

View File

@ -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 different 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.

View File

@ -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"

View File

@ -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())

View File

@ -14,6 +14,7 @@ add_tablegen(clang-tblgen CLANG
ClangOpenCLBuiltinEmitter.cpp
ClangOptionDocEmitter.cpp
ClangSACheckersEmitter.cpp
ClangSyntaxEmitter.cpp
ClangTypeNodesEmitter.cpp
MveEmitter.cpp
NeonEmitter.cpp

View File

@ -0,0 +1,130 @@
//===- 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;
bool Inserted = ByName.try_emplace(R->getName(), &AllTypes.back()).second;
assert(Inserted && "Duplicate node name");
(void)Inserted;
}
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";
}

View File

@ -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;

View File

@ -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);