diff --git a/clang/include/clang/CMakeLists.txt b/clang/include/clang/CMakeLists.txt --- a/clang/include/clang/CMakeLists.txt +++ b/clang/include/clang/CMakeLists.txt @@ -5,3 +5,4 @@ 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 --- /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 --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -35,82 +35,8 @@ /// 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 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 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 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 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 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 @@ 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 @@ 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 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 getSpecifiers(); std::vector> getSpecifiersAndDoubleColons(); @@ -286,9 +192,7 @@ 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::size`. @@ -301,9 +205,7 @@ 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 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 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 getArguments(); std::vector> getArgumentsAndCommas(); }; @@ -351,9 +247,7 @@ 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 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 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ public: PrefixUnaryOperatorExpression() : UnaryOperatorExpression(NodeKind::PrefixUnaryOperatorExpression) {} - static bool classof(const Node *N) { - return N->getKind() == NodeKind::PrefixUnaryOperatorExpression; - } + static bool classof(const Node *N); }; /// @@ -575,9 +424,7 @@ public: PostfixUnaryOperatorExpression() : UnaryOperatorExpression(NodeKind::PostfixUnaryOperatorExpression) {} - static bool classof(const Node *N) { - return N->getKind() == NodeKind::PostfixUnaryOperatorExpression; - } + static bool classof(const Node *N); }; /// @@ -590,9 +437,7 @@ 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 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 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 () 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 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 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 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 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 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 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 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 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 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 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 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 getStatements(); @@ -781,28 +593,21 @@ 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(, ) @@ -810,9 +615,7 @@ 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 @@ 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 getDeclarators(); std::vector> getDeclaratorsAndCommas(); @@ -845,9 +644,7 @@ 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 getDeclarators(); }; @@ -856,9 +653,7 @@ 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 @@ 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 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 = @@ -894,18 +685,14 @@ public: NamespaceAliasDefinition() : Declaration(NodeKind::NamespaceAliasDefinition) {} - static bool classof(const Node *N) { - return N->getKind() == NodeKind::NamespaceAliasDefinition; - } + static bool classof(const Node *N); }; /// using namespace 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 :: @@ -913,18 +700,14 @@ 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 = 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 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 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 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 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 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 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 getParameterDeclarations(); std::vector> getParametersAndCommas(); @@ -1029,9 +799,7 @@ 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 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 --- /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 {} +def Tree : External {} + +def TranslationUnit : External {} + +def Expression : External {} +def UnknownExpression : External {} +def UnaryOperatorExpression : External {} +def PrefixUnaryOperatorExpression : External {} +def PostfixUnaryOperatorExpression : External {} +def BinaryOperatorExpression : External {} +def ParenExpression : External {} +def LiteralExpression : External {} +def IntegerLiteralExpression : External {} +def CharacterLiteralExpression : External {} +def FloatingLiteralExpression : External {} +def StringLiteralExpression : External {} +def BoolLiteralExpression : External {} +def CxxNullPtrExpression : External {} +def UserDefinedLiteralExpression : External {} +def IntegerUserDefinedLiteralExpression : External {} +def FloatUserDefinedLiteralExpression : External {} +def CharUserDefinedLiteralExpression : External {} +def StringUserDefinedLiteralExpression : External {} +def IdExpression : External {} +def MemberExpression : External {} +def ThisExpression : External {} +def CallExpression : External {} + +// Statements. +def Statement : External {} +def UnknownStatement : External {} +def DeclarationStatement : External {} +def EmptyStatement : External {} +def SwitchStatement : External {} +def CaseStatement : External {} +def DefaultStatement : External {} +def IfStatement : External {} +def ForStatement : External {} +def WhileStatement : External {} +def ContinueStatement : External {} +def BreakStatement : External {} +def ReturnStatement : External {} +def RangeBasedForStatement : External {} +def ExpressionStatement : External {} +def CompoundStatement : External {} + +// Declarations. +def Declaration : External {} +def UnknownDeclaration : External {} +def EmptyDeclaration : External {} +def StaticAssertDeclaration : External {} +def LinkageSpecificationDeclaration : External {} +def SimpleDeclaration : External {} +def TemplateDeclaration : External {} +def ExplicitTemplateInstantiation : External {} +def NamespaceDefinition : External {} +def NamespaceAliasDefinition : External {} +def UsingNamespaceDirective : External {} +def UsingDeclaration : External {} +def TypeAliasDeclaration : External {} + +// Declarators. +def Declarator : External {} +def SimpleDeclarator : External {} +def ParenDeclarator : External {} + +def ArraySubscript : External {} +def TrailingReturnType : External {} +def ParametersAndQualifiers : External {} +def MemberPointer : External {} +def UnqualifiedId : External {} + +// Lists +def List : External {} +def DeclaratorList : External {} +def ParameterDeclarationList : External {} +def CallArguments : External {} +def NestedNameSpecifier : External {} + +// Name Specifiers. +def NameSpecifier : External {} +def GlobalNameSpecifier : External {} +def DecltypeNameSpecifier : External {} +def IdentifierNameSpecifier : External {} +def SimpleTemplateNameSpecifier : External {} diff --git a/clang/include/clang/Tooling/Syntax/Syntax.td b/clang/include/clang/Tooling/Syntax/Syntax.td new file mode 100644 --- /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 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 { 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 --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -630,3 +630,7 @@ return cast_or_null( 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 --- a/clang/lib/Tooling/Syntax/Tree.cpp +++ b/clang/lib/Tooling/Syntax/Tree.cpp @@ -52,10 +52,6 @@ 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(Kind)), Role(0), Original(false), @@ -71,10 +67,6 @@ this->Role = static_cast(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 @@ 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::getElementsAsNodesAndDelimiters() { if (!getFirstChild()) diff --git a/clang/utils/TableGen/CMakeLists.txt b/clang/utils/TableGen/CMakeLists.txt --- a/clang/utils/TableGen/CMakeLists.txt +++ b/clang/utils/TableGen/CMakeLists.txt @@ -14,6 +14,7 @@ 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 --- /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 + +#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 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 AllTypes; + llvm::DenseMap 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 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -55,6 +55,7 @@ GenClangTypeWriter, GenClangOpcodes, GenClangSACheckers, + GenClangSyntaxNodeList, GenClangCommentHTMLTags, GenClangCommentHTMLTagsProperties, GenClangCommentHTMLNamedCharacterReferences, @@ -166,6 +167,8 @@ "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 @@ 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 --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -83,6 +83,9 @@ 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);