eduucaldas created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82302

Files:
  clang/include/clang/Tooling/Syntax/Nodes.h

Index: clang/include/clang/Tooling/Syntax/Nodes.h
===================================================================
--- clang/include/clang/Tooling/Syntax/Nodes.h
+++ clang/include/clang/Tooling/Syntax/Nodes.h
@@ -45,6 +45,7 @@
   BinaryOperatorExpression,
   CxxNullPtrExpression,
   IntegerLiteralExpression,
+  IdExpression,
 
   // Statements.
   UnknownStatement,
@@ -84,7 +85,12 @@
   ArraySubscript,
   TrailingReturnType,
   ParametersAndQualifiers,
-  MemberPointer
+  MemberPointer,
+  NestedNameSpecifier,
+  NameSpecifier,
+  NamespaceName,
+  UnqualifiedId,
+  OperatorFunctionId,
 };
 /// For debugging purposes.
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K);
@@ -187,6 +193,130 @@
   }
 };
 
+/// A sequence of these specifiers make a `nested-name-specifier`.
+/// e.g. the `std::` or `vector<int>::` in `std::vector<int>::size`.
+/// nested-name-specifier:
+///   ::
+///   type-name ::
+///   namespace-name ::
+///   decltype-specifier ::
+///   nested-name-specifier identifier ::
+///   nested-name-specifier template_opt simple-template-id ::
+class NameSpecifier final : public Tree {
+private:
+  // See discussion about implementation in UnqualifiedId
+  enum SpecifierKind {
+    Global,
+    TypeSpec,
+    Namespace,
+    DecltypeSpec,
+    Identifier,
+    TypeSpecWithTemplate
+  };
+
+public:
+  NameSpecifier() : Tree(NodeKind::NameSpecifier) {}
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::NameSpecifier;
+  }
+  SpecifierKind getKind();
+  syntax::Leaf *getIdentifier();
+  syntax::Leaf *getNamespaceName();
+  //(...)
+  syntax::Leaf &doubleCommaToken();
+};
+
+/// 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 Tree {
+public:
+  NestedNameSpecifier() : Tree(NodeKind::NestedNameSpecifier) {}
+  static bool classof(const Node *N) {
+    return N->kind() <= NodeKind::NestedNameSpecifier;
+  }
+  std::vector<syntax::NameSpecifier &> specifiers();
+};
+
+/// Models a `operator-function-id`. C++ [over.oper]
+/// operator-function-id:
+///   'operator' operator
+/// operator:
+///   +   -   *   /   =
+/// (...)
+class OperatorFunctionId final : public Tree {
+public:
+  OperatorFunctionId() : Tree(NodeKind::OperatorFunctionId) {}
+  static bool classof(const Node *N) {
+    return N->kind() <= NodeKind::OperatorFunctionId;
+  }
+  syntax::Leaf &operatorKeyword();
+  syntax::Leaf &operatorCode();
+};
+
+/// Models an `unqualified-id`.  / e.g. the `size` in `std::vector<int>::size`.
+// C++ [expr.prim.id.unqual]
+// unqualified-id:
+//   identifier
+//   operator-function-id
+//   conversion-function-id
+//   literal-operator-id
+//   ~ type-name
+//   ~ decltype-specifier
+//   template-id
+class UnqualifiedId final : public Tree {
+  // The variants of `unqualified-id` - `identifier`, `operator-function-id`,
+  // ... - appear in other parts of the syntax. As such we want to implement
+  // them detached from `unqualified-id`. How to implement accessors to these
+  // variants?
+  //  * Store an union with the variants and an enum of the kinds of
+  //    variants. Access these variants by asking of what kind is
+  //    `unqualified-id` and then using the appropriate getter. See:
+  //    `UnqualifiedId` in "llvm-project/clang/include/clang/Sema/DeclSpec.h".
+  //  * Similar but using std::variant instead of union.
+  //  * not implement those accessors.
+private:
+  enum class UnqualifiedIdKind {
+    IK_Identifier,
+    IK_OperatorFunctionId,
+    IK_ConversionFunctionId,
+    IK_LiteralOperatorId,
+    IK_DestructorName,
+    IK_TemplateId,
+  };
+
+public:
+  UnqualifiedId() : Tree(NodeKind::UnqualifiedId) {}
+  static bool classof(const Node *N) {
+    return N->kind() == NodeKind::UnqualifiedId;
+  }
+  UnqualifiedIdKind getKind();
+  syntax::Leaf *getIdentifier();
+  syntax::OperatorFunctionId *getOperatorFunctionId();
+  // (...)
+};
+
+/// 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->kind() == NodeKind::IdExpression;
+  }
+  // `qualifier` and `templateKeyword` are optional children of
+  // id-expression whereas id is a required child.
+  // How to make this distinction clear both to the reader and to the compiler?
+  syntax::NestedNameSpecifier *qualifier();
+  syntax::Leaf *templateKeyword();
+
+  syntax::UnqualifiedId &id();
+};
+
 /// C++11 'nullptr' expression.
 class CxxNullPtrExpression final : public Expression {
 public:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to