| //===- Nodes.h - syntax nodes for C/C++ grammar constructs ----*- C++ -*-=====// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // Syntax tree nodes for C, C++ and Objective-C grammar constructs. |
| // |
| // Nodes provide access to their syntactic components, e.g. IfStatement provides |
| // a way to get its condition, then and else branches, tokens for 'if' and |
| // 'else' keywords. |
| // When using the accessors, please assume they can return null. This happens |
| // because: |
| // - the corresponding subnode is optional in the C++ grammar, e.g. an else |
| // branch of an if statement, |
| // - syntactic errors occurred while parsing the corresponding subnode. |
| // One notable exception is "introducer" keywords, e.g. the accessor for the |
| // 'if' keyword of an if statement will never return null. |
| //===----------------------------------------------------------------------===// |
| #ifndef LLVM_CLANG_TOOLING_SYNTAX_NODES_H |
| #define LLVM_CLANG_TOOLING_SYNTAX_NODES_H |
| |
| #include "clang/Basic/TokenKinds.h" |
| #include "clang/Lex/Token.h" |
| #include "clang/Tooling/Syntax/Tokens.h" |
| #include "clang/Tooling/Syntax/Tree.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/raw_ostream.h" |
| namespace clang { |
| namespace syntax { |
| |
| /// A kind of a syntax node, used for implementing casts. The ordering and |
| /// 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, |
| }; |
| /// For debugging purposes. |
| raw_ostream &operator<<(raw_ostream &OS, NodeKind K); |
| |
| /// A relation between a parent and child node, e.g. 'left-hand-side of |
| /// a binary expression'. Used for implementing accessors. |
| /// |
| /// In general `NodeRole`s should be named the same as their accessors. |
| /// |
| /// Some roles describe parent/child relations that occur multiple times in |
| /// language grammar. We define only one role to describe all instances of such |
| /// recurring relations. For example, grammar for both "if" and "while" |
| /// statements requires an opening paren and a closing paren. The opening |
| /// paren token is assigned the OpenParen role regardless of whether it appears |
| /// as a child of IfStatement or WhileStatement node. More generally, when |
| /// grammar requires a certain fixed token (like a specific keyword, or an |
| /// opening paren), we define a role for this token and use it across all |
| /// grammar rules with the same requirement. Names of such reusable roles end |
| /// with a ~Token or a ~Keyword suffix. |
| enum class NodeRole : uint8_t { |
| // Roles common to multiple node kinds. |
| /// A node without a parent |
| Detached, |
| /// Children of an unknown semantic nature, e.g. skipped tokens, comments. |
| Unknown, |
| /// An opening parenthesis in argument lists and blocks, e.g. '{', '(', etc. |
| OpenParen, |
| /// A closing parenthesis in argument lists and blocks, e.g. '}', ')', etc. |
| CloseParen, |
| /// A keywords that introduces some grammar construct, e.g. 'if', 'try', etc. |
| IntroducerKeyword, |
| /// A token that represents a literal, e.g. 'nullptr', '1', 'true', etc. |
| LiteralToken, |
| /// Tokens or Keywords. |
| ArrowToken, |
| ExternKeyword, |
| TemplateKeyword, |
| /// An inner statement for those that have only a single child of kind |
| /// statement, e.g. loop body for while, for, etc; inner statement for case, |
| /// default, etc. |
| BodyStatement, |
| /// List API roles. |
| ListElement, |
| ListDelimiter, |
| |
| // Roles specific to particular node kinds. |
| OperatorToken, |
| Operand, |
| LeftHandSide, |
| RightHandSide, |
| ReturnValue, |
| CaseValue, |
| ThenStatement, |
| ElseKeyword, |
| ElseStatement, |
| Expression, |
| Statement, |
| Condition, |
| Message, |
| Declarator, |
| Declaration, |
| Size, |
| Parameters, |
| TrailingReturn, |
| UnqualifiedId, |
| Qualifier, |
| SubExpression, |
| Object, |
| AccessToken, |
| Member, |
| Callee, |
| Arguments, |
| Declarators |
| }; |
| /// For debugging purposes. |
| raw_ostream &operator<<(raw_ostream &OS, NodeRole R); |
| |
| class SimpleDeclarator; |
| |
| /// A root node for a translation unit. Parent is always null. |
| class TranslationUnit final : public Tree { |
| public: |
| TranslationUnit() : Tree(NodeKind::TranslationUnit) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::TranslationUnit; |
| } |
| }; |
| |
| /// A base class for all expressions. Note that expressions are not statements, |
| /// even though they are in clang. |
| 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; |
| } |
| }; |
| |
| /// A sequence of these specifiers make a `nested-name-specifier`. |
| /// e.g. the `std` or `vector<int>` in `std::vector<int>::size`. |
| 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; |
| } |
| }; |
| |
| /// The global namespace name specifier, this specifier doesn't correspond to a |
| /// token instead an absence of tokens before a `::` characterizes it, in |
| /// `::std::vector<int>` it would be characterized by the absence of a token |
| /// before the first `::` |
| class GlobalNameSpecifier final : public NameSpecifier { |
| public: |
| GlobalNameSpecifier() : NameSpecifier(NodeKind::GlobalNameSpecifier) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::GlobalNameSpecifier; |
| } |
| }; |
| |
| /// A name specifier holding a decltype, of the form: `decltype ( expression ) ` |
| /// e.g. the `decltype(s)` in `decltype(s)::size`. |
| class DecltypeNameSpecifier final : public NameSpecifier { |
| public: |
| DecltypeNameSpecifier() : NameSpecifier(NodeKind::DecltypeNameSpecifier) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::DecltypeNameSpecifier; |
| } |
| }; |
| |
| /// A identifier name specifier, of the form `identifier` |
| /// e.g. the `std` in `std::vector<int>::size`. |
| class IdentifierNameSpecifier final : public NameSpecifier { |
| public: |
| IdentifierNameSpecifier() |
| : NameSpecifier(NodeKind::IdentifierNameSpecifier) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::IdentifierNameSpecifier; |
| } |
| }; |
| |
| /// A name specifier with a simple-template-id, of the form `template_opt |
| /// identifier < template-args >` e.g. the `vector<int>` in |
| /// `std::vector<int>::size`. |
| class SimpleTemplateNameSpecifier final : public NameSpecifier { |
| public: |
| SimpleTemplateNameSpecifier() |
| : NameSpecifier(NodeKind::SimpleTemplateNameSpecifier) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::SimpleTemplateNameSpecifier; |
| } |
| }; |
| |
| /// Models a `nested-name-specifier`. C++ [expr.prim.id.qual] |
| /// e.g. the `std::vector<int>::` in `std::vector<int>::size`. |
| class NestedNameSpecifier final : public List { |
| public: |
| NestedNameSpecifier() : List(NodeKind::NestedNameSpecifier) {} |
| static bool classof(const Node *N) { |
| return N->getKind() <= NodeKind::NestedNameSpecifier; |
| } |
| std::vector<NameSpecifier *> getSpecifiers(); |
| std::vector<List::ElementAndDelimiter<syntax::NameSpecifier>> |
| getSpecifiersAndDoubleColons(); |
| }; |
| |
| /// Models an `unqualified-id`. C++ [expr.prim.id.unqual] |
| /// e.g. the `size` in `std::vector<int>::size`. |
| class UnqualifiedId final : public Tree { |
| public: |
| UnqualifiedId() : Tree(NodeKind::UnqualifiedId) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::UnqualifiedId; |
| } |
| }; |
| |
| /// Models an `id-expression`, e.g. `std::vector<int>::size`. |
| /// C++ [expr.prim.id] |
| /// id-expression: |
| /// unqualified-id |
| /// qualified-id |
| /// qualified-id: |
| /// nested-name-specifier template_opt unqualified-id |
| class IdExpression final : public Expression { |
| public: |
| IdExpression() : Expression(NodeKind::IdExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::IdExpression; |
| } |
| NestedNameSpecifier *getQualifier(); |
| Leaf *getTemplateKeyword(); |
| UnqualifiedId *getUnqualifiedId(); |
| }; |
| |
| /// An expression of an unknown kind, i.e. one not currently handled by the |
| /// syntax tree. |
| class UnknownExpression final : public Expression { |
| public: |
| UnknownExpression() : Expression(NodeKind::UnknownExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::UnknownExpression; |
| } |
| }; |
| |
| /// 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; |
| } |
| Leaf *getThisKeyword(); |
| }; |
| |
| /// Models arguments of a function call. |
| /// call-arguments: |
| /// delimited_list(expression, ',') |
| /// Note: This construct is a simplification of the grammar rule for |
| /// `expression-list`, that is used in the definition of `call-expression` |
| class CallArguments final : public List { |
| public: |
| CallArguments() : List(NodeKind::CallArguments) {} |
| static bool classof(const Node *N) { |
| return N->getKind() <= NodeKind::CallArguments; |
| } |
| std::vector<Expression *> getArguments(); |
| std::vector<List::ElementAndDelimiter<Expression>> getArgumentsAndCommas(); |
| }; |
| |
| /// A function call. C++ [expr.call] |
| /// call-expression: |
| /// expression '(' call-arguments ')' |
| /// e.g `f(1, '2')` or `this->Base::f()` |
| class CallExpression final : public Expression { |
| public: |
| CallExpression() : Expression(NodeKind::CallExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::CallExpression; |
| } |
| Expression *getCallee(); |
| Leaf *getOpenParen(); |
| CallArguments *getArguments(); |
| Leaf *getCloseParen(); |
| }; |
| |
| /// Models a parenthesized expression `(E)`. C++ [expr.prim.paren] |
| /// e.g. `(3 + 2)` in `a = 1 + (3 + 2);` |
| class ParenExpression final : public Expression { |
| public: |
| ParenExpression() : Expression(NodeKind::ParenExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ParenExpression; |
| } |
| Leaf *getOpenParen(); |
| Expression *getSubExpression(); |
| Leaf *getCloseParen(); |
| }; |
| |
| /// Models a class member access. C++ [expr.ref] |
| /// member-expression: |
| /// expression -> template_opt id-expression |
| /// expression . template_opt id-expression |
| /// e.g. `x.a`, `xp->a` |
| /// |
| /// Note: An implicit member access inside a class, i.e. `a` instead of |
| /// `this->a`, is an `id-expression`. |
| class MemberExpression final : public Expression { |
| public: |
| MemberExpression() : Expression(NodeKind::MemberExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::MemberExpression; |
| } |
| Expression *getObject(); |
| Leaf *getAccessToken(); |
| Leaf *getTemplateKeyword(); |
| IdExpression *getMember(); |
| }; |
| |
| /// Expression for literals. C++ [lex.literal] |
| 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; |
| } |
| Leaf *getLiteralToken(); |
| }; |
| |
| /// Expression for integer literals. C++ [lex.icon] |
| class IntegerLiteralExpression final : public LiteralExpression { |
| public: |
| IntegerLiteralExpression() |
| : LiteralExpression(NodeKind::IntegerLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::IntegerLiteralExpression; |
| } |
| }; |
| |
| /// Expression for character literals. C++ [lex.ccon] |
| class CharacterLiteralExpression final : public LiteralExpression { |
| public: |
| CharacterLiteralExpression() |
| : LiteralExpression(NodeKind::CharacterLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::CharacterLiteralExpression; |
| } |
| }; |
| |
| /// Expression for floating-point literals. C++ [lex.fcon] |
| class FloatingLiteralExpression final : public LiteralExpression { |
| public: |
| FloatingLiteralExpression() |
| : LiteralExpression(NodeKind::FloatingLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::FloatingLiteralExpression; |
| } |
| }; |
| |
| /// Expression for string-literals. C++ [lex.string] |
| class StringLiteralExpression final : public LiteralExpression { |
| public: |
| StringLiteralExpression() |
| : LiteralExpression(NodeKind::StringLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::StringLiteralExpression; |
| } |
| }; |
| |
| /// Expression for boolean literals. C++ [lex.bool] |
| class BoolLiteralExpression final : public LiteralExpression { |
| public: |
| BoolLiteralExpression() |
| : LiteralExpression(NodeKind::BoolLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::BoolLiteralExpression; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// Expression for user-defined literal. C++ [lex.ext] |
| /// user-defined-literal: |
| /// user-defined-integer-literal |
| /// user-defined-floating-point-literal |
| /// user-defined-string-literal |
| /// user-defined-character-literal |
| 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; |
| } |
| }; |
| |
| /// Expression for user-defined-integer-literal. C++ [lex.ext] |
| class IntegerUserDefinedLiteralExpression final |
| : public UserDefinedLiteralExpression { |
| public: |
| IntegerUserDefinedLiteralExpression() |
| : UserDefinedLiteralExpression( |
| NodeKind::IntegerUserDefinedLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::IntegerUserDefinedLiteralExpression; |
| } |
| }; |
| |
| /// Expression for user-defined-floating-point-literal. C++ [lex.ext] |
| class FloatUserDefinedLiteralExpression final |
| : public UserDefinedLiteralExpression { |
| public: |
| FloatUserDefinedLiteralExpression() |
| : UserDefinedLiteralExpression( |
| NodeKind::FloatUserDefinedLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::FloatUserDefinedLiteralExpression; |
| } |
| }; |
| |
| /// Expression for user-defined-character-literal. C++ [lex.ext] |
| class CharUserDefinedLiteralExpression final |
| : public UserDefinedLiteralExpression { |
| public: |
| CharUserDefinedLiteralExpression() |
| : UserDefinedLiteralExpression( |
| NodeKind::CharUserDefinedLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::CharUserDefinedLiteralExpression; |
| } |
| }; |
| |
| /// Expression for user-defined-string-literal. C++ [lex.ext] |
| class StringUserDefinedLiteralExpression final |
| : public UserDefinedLiteralExpression { |
| public: |
| StringUserDefinedLiteralExpression() |
| : UserDefinedLiteralExpression( |
| NodeKind::StringUserDefinedLiteralExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::StringUserDefinedLiteralExpression; |
| } |
| }; |
| |
| /// 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; |
| } |
| Leaf *getOperatorToken(); |
| Expression *getOperand(); |
| }; |
| |
| /// <operator> <operand> |
| /// |
| /// For example: |
| /// +a -b |
| /// !c not c |
| /// ~d compl d |
| /// *e &f |
| /// ++h --h |
| /// __real i __imag i |
| class PrefixUnaryOperatorExpression final : public UnaryOperatorExpression { |
| public: |
| PrefixUnaryOperatorExpression() |
| : UnaryOperatorExpression(NodeKind::PrefixUnaryOperatorExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::PrefixUnaryOperatorExpression; |
| } |
| }; |
| |
| /// <operand> <operator> |
| /// |
| /// For example: |
| /// a++ |
| /// b-- |
| class PostfixUnaryOperatorExpression final : public UnaryOperatorExpression { |
| public: |
| PostfixUnaryOperatorExpression() |
| : UnaryOperatorExpression(NodeKind::PostfixUnaryOperatorExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::PostfixUnaryOperatorExpression; |
| } |
| }; |
| |
| /// <lhs> <operator> <rhs> |
| /// |
| /// For example: |
| /// a + b |
| /// a bitor 1 |
| /// a |= b |
| /// a and_eq b |
| class BinaryOperatorExpression final : public Expression { |
| public: |
| BinaryOperatorExpression() : Expression(NodeKind::BinaryOperatorExpression) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::BinaryOperatorExpression; |
| } |
| Expression *getLhs(); |
| Leaf *getOperatorToken(); |
| Expression *getRhs(); |
| }; |
| |
| /// An abstract node for C++ statements, e.g. 'while', 'if', etc. |
| /// FIXME: add accessors for semicolon of statements that have it. |
| 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; |
| } |
| }; |
| |
| /// A statement of an unknown kind, i.e. one not currently handled by the syntax |
| /// tree. |
| class UnknownStatement final : public Statement { |
| public: |
| UnknownStatement() : Statement(NodeKind::UnknownStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::UnknownStatement; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// switch (<cond>) <body> |
| class SwitchStatement final : public Statement { |
| public: |
| SwitchStatement() : Statement(NodeKind::SwitchStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::SwitchStatement; |
| } |
| Leaf *getSwitchKeyword(); |
| Statement *getBody(); |
| }; |
| |
| /// case <value>: <body> |
| class CaseStatement final : public Statement { |
| public: |
| CaseStatement() : Statement(NodeKind::CaseStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::CaseStatement; |
| } |
| Leaf *getCaseKeyword(); |
| Expression *getCaseValue(); |
| Statement *getBody(); |
| }; |
| |
| /// default: <body> |
| class DefaultStatement final : public Statement { |
| public: |
| DefaultStatement() : Statement(NodeKind::DefaultStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::DefaultStatement; |
| } |
| Leaf *getDefaultKeyword(); |
| Statement *getBody(); |
| }; |
| |
| /// if (cond) <then-statement> else <else-statement> |
| /// FIXME: add condition that models 'expression or variable declaration' |
| class IfStatement final : public Statement { |
| public: |
| IfStatement() : Statement(NodeKind::IfStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::IfStatement; |
| } |
| Leaf *getIfKeyword(); |
| Statement *getThenStatement(); |
| Leaf *getElseKeyword(); |
| Statement *getElseStatement(); |
| }; |
| |
| /// for (<init>; <cond>; <increment>) <body> |
| class ForStatement final : public Statement { |
| public: |
| ForStatement() : Statement(NodeKind::ForStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ForStatement; |
| } |
| Leaf *getForKeyword(); |
| Statement *getBody(); |
| }; |
| |
| /// while (<cond>) <body> |
| class WhileStatement final : public Statement { |
| public: |
| WhileStatement() : Statement(NodeKind::WhileStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::WhileStatement; |
| } |
| Leaf *getWhileKeyword(); |
| Statement *getBody(); |
| }; |
| |
| /// continue; |
| class ContinueStatement final : public Statement { |
| public: |
| ContinueStatement() : Statement(NodeKind::ContinueStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ContinueStatement; |
| } |
| Leaf *getContinueKeyword(); |
| }; |
| |
| /// break; |
| class BreakStatement final : public Statement { |
| public: |
| BreakStatement() : Statement(NodeKind::BreakStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::BreakStatement; |
| } |
| Leaf *getBreakKeyword(); |
| }; |
| |
| /// return <expr>; |
| /// return; |
| class ReturnStatement final : public Statement { |
| public: |
| ReturnStatement() : Statement(NodeKind::ReturnStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ReturnStatement; |
| } |
| Leaf *getReturnKeyword(); |
| Expression *getReturnValue(); |
| }; |
| |
| /// for (<decl> : <init>) <body> |
| class RangeBasedForStatement final : public Statement { |
| public: |
| RangeBasedForStatement() : Statement(NodeKind::RangeBasedForStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::RangeBasedForStatement; |
| } |
| Leaf *getForKeyword(); |
| Statement *getBody(); |
| }; |
| |
| /// Expression in a statement position, e.g. functions calls inside compound |
| /// statements or inside a loop body. |
| class ExpressionStatement final : public Statement { |
| public: |
| ExpressionStatement() : Statement(NodeKind::ExpressionStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ExpressionStatement; |
| } |
| Expression *getExpression(); |
| }; |
| |
| /// { statement1; statement2; … } |
| class CompoundStatement final : public Statement { |
| public: |
| CompoundStatement() : Statement(NodeKind::CompoundStatement) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::CompoundStatement; |
| } |
| Leaf *getLbrace(); |
| /// FIXME: use custom iterator instead of 'vector'. |
| std::vector<Statement *> getStatements(); |
| Leaf *getRbrace(); |
| }; |
| |
| /// A declaration that can appear at the top-level. Note that this does *not* |
| /// correspond 1-to-1 to clang::Decl. Syntax trees distinguish between top-level |
| /// declarations (e.g. namespace definitions) and declarators (e.g. variables, |
| /// typedefs, etc.). Declarators are stored inside SimpleDeclaration. |
| 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; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// 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_assert(<condition>, <message>) |
| /// static_assert(<condition>) |
| class StaticAssertDeclaration final : public Declaration { |
| public: |
| StaticAssertDeclaration() : Declaration(NodeKind::StaticAssertDeclaration) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::StaticAssertDeclaration; |
| } |
| Expression *getCondition(); |
| Expression *getMessage(); |
| }; |
| |
| /// extern <string-literal> declaration |
| /// extern <string-literal> { <decls> } |
| class LinkageSpecificationDeclaration final : public Declaration { |
| public: |
| LinkageSpecificationDeclaration() |
| : Declaration(NodeKind::LinkageSpecificationDeclaration) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::LinkageSpecificationDeclaration; |
| } |
| }; |
| |
| class DeclaratorList final : public List { |
| public: |
| DeclaratorList() : List(NodeKind::DeclaratorList) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::DeclaratorList; |
| } |
| std::vector<SimpleDeclarator *> getDeclarators(); |
| std::vector<List::ElementAndDelimiter<syntax::SimpleDeclarator>> |
| getDeclaratorsAndCommas(); |
| }; |
| |
| /// Groups multiple declarators (e.g. variables, typedefs, etc.) together. All |
| /// grouped declarators share the same declaration specifiers (e.g. 'int' or |
| /// 'typedef'). |
| class SimpleDeclaration final : public Declaration { |
| public: |
| SimpleDeclaration() : Declaration(NodeKind::SimpleDeclaration) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::SimpleDeclaration; |
| } |
| /// FIXME: use custom iterator instead of 'vector'. |
| std::vector<SimpleDeclarator *> getDeclarators(); |
| }; |
| |
| /// template <template-parameters> <declaration> |
| class TemplateDeclaration final : public Declaration { |
| public: |
| TemplateDeclaration() : Declaration(NodeKind::TemplateDeclaration) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::TemplateDeclaration; |
| } |
| Leaf *getTemplateKeyword(); |
| Declaration *getDeclaration(); |
| }; |
| |
| /// template <declaration> |
| /// Examples: |
| /// template struct X<int> |
| /// template void foo<int>() |
| /// template int var<double> |
| class ExplicitTemplateInstantiation final : public Declaration { |
| public: |
| ExplicitTemplateInstantiation() |
| : Declaration(NodeKind::ExplicitTemplateInstantiation) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ExplicitTemplateInstantiation; |
| } |
| Leaf *getTemplateKeyword(); |
| Leaf *getExternKeyword(); |
| Declaration *getDeclaration(); |
| }; |
| |
| /// namespace <name> { <decls> } |
| class NamespaceDefinition final : public Declaration { |
| public: |
| NamespaceDefinition() : Declaration(NodeKind::NamespaceDefinition) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::NamespaceDefinition; |
| } |
| }; |
| |
| /// namespace <name> = <namespace-reference> |
| class NamespaceAliasDefinition final : public Declaration { |
| public: |
| NamespaceAliasDefinition() |
| : Declaration(NodeKind::NamespaceAliasDefinition) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::NamespaceAliasDefinition; |
| } |
| }; |
| |
| /// using namespace <name> |
| class UsingNamespaceDirective final : public Declaration { |
| public: |
| UsingNamespaceDirective() : Declaration(NodeKind::UsingNamespaceDirective) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::UsingNamespaceDirective; |
| } |
| }; |
| |
| /// using <scope>::<name> |
| /// using typename <scope>::<name> |
| class UsingDeclaration final : public Declaration { |
| public: |
| UsingDeclaration() : Declaration(NodeKind::UsingDeclaration) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::UsingDeclaration; |
| } |
| }; |
| |
| /// using <name> = <type> |
| class TypeAliasDeclaration final : public Declaration { |
| public: |
| TypeAliasDeclaration() : Declaration(NodeKind::TypeAliasDeclaration) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::TypeAliasDeclaration; |
| } |
| }; |
| |
| /// Covers a name, an initializer and a part of the type outside declaration |
| /// specifiers. Examples are: |
| /// `*a` in `int *a` |
| /// `a[10]` in `int a[10]` |
| /// `*a = nullptr` in `int *a = nullptr` |
| /// Declarators can be unnamed too: |
| /// `**` in `new int**` |
| /// `* = nullptr` in `void foo(int* = nullptr)` |
| /// Most declarators you encounter are instances of SimpleDeclarator. They may |
| /// contain an inner declarator inside parentheses, we represent it as |
| /// ParenDeclarator. E.g. |
| /// `(*a)` in `int (*a) = 10` |
| 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; |
| } |
| }; |
| |
| /// A top-level declarator without parentheses. See comment of Declarator for |
| /// more details. |
| class SimpleDeclarator final : public Declarator { |
| public: |
| SimpleDeclarator() : Declarator(NodeKind::SimpleDeclarator) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::SimpleDeclarator; |
| } |
| }; |
| |
| /// Declarator inside parentheses. |
| /// E.g. `(***a)` from `int (***a) = nullptr;` |
| /// See comment of Declarator for more details. |
| class ParenDeclarator final : public Declarator { |
| public: |
| ParenDeclarator() : Declarator(NodeKind::ParenDeclarator) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ParenDeclarator; |
| } |
| Leaf *getLparen(); |
| Leaf *getRparen(); |
| }; |
| |
| /// Array size specified inside a declarator. |
| /// E.g: |
| /// `[10]` in `int a[10];` |
| /// `[static 10]` in `void f(int xs[static 10]);` |
| class ArraySubscript final : public Tree { |
| public: |
| ArraySubscript() : Tree(NodeKind::ArraySubscript) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ArraySubscript; |
| } |
| // TODO: add an accessor for the "static" keyword. |
| Leaf *getLbracket(); |
| Expression *getSize(); |
| Leaf *getRbracket(); |
| }; |
| |
| /// Trailing return type after the parameter list, including the arrow token. |
| /// E.g. `-> int***`. |
| class TrailingReturnType final : public Tree { |
| public: |
| TrailingReturnType() : Tree(NodeKind::TrailingReturnType) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::TrailingReturnType; |
| } |
| // TODO: add accessors for specifiers. |
| Leaf *getArrowToken(); |
| // FIXME: This should be a `type-id` following the grammar. Fix this once we |
| // have a representation of `type-id`s. |
| SimpleDeclarator *getDeclarator(); |
| }; |
| |
| /// Models a `parameter-declaration-list` which appears within |
| /// `parameters-and-qualifiers`. See C++ [dcl.fct] |
| class ParameterDeclarationList final : public List { |
| public: |
| ParameterDeclarationList() : List(NodeKind::ParameterDeclarationList) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ParameterDeclarationList; |
| } |
| std::vector<SimpleDeclaration *> getParameterDeclarations(); |
| std::vector<List::ElementAndDelimiter<syntax::SimpleDeclaration>> |
| getParametersAndCommas(); |
| }; |
| |
| /// Parameter list for a function type and a trailing return type, if the |
| /// function has one. |
| /// E.g.: |
| /// `(int a) volatile ` in `int foo(int a) volatile;` |
| /// `(int a) &&` in `int foo(int a) &&;` |
| /// `() -> int` in `auto foo() -> int;` |
| /// `() const` in `int foo() const;` |
| /// `() noexcept` in `int foo() noexcept;` |
| /// `() throw()` in `int foo() throw();` |
| /// |
| /// (!) override doesn't belong here. |
| class ParametersAndQualifiers final : public Tree { |
| public: |
| ParametersAndQualifiers() : Tree(NodeKind::ParametersAndQualifiers) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::ParametersAndQualifiers; |
| } |
| Leaf *getLparen(); |
| ParameterDeclarationList *getParameters(); |
| Leaf *getRparen(); |
| TrailingReturnType *getTrailingReturn(); |
| }; |
| |
| /// Member pointer inside a declarator |
| /// E.g. `X::*` in `int X::* a = 0;` |
| class MemberPointer final : public Tree { |
| public: |
| MemberPointer() : Tree(NodeKind::MemberPointer) {} |
| static bool classof(const Node *N) { |
| return N->getKind() == NodeKind::MemberPointer; |
| } |
| }; |
| |
| } // namespace syntax |
| } // namespace clang |
| #endif |