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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D84781

Files:
  clang/include/clang/Tooling/Syntax/Nodes.h
  clang/include/clang/Tooling/Syntax/Tree.h
  clang/lib/Tooling/Syntax/BuildTree.cpp
  clang/lib/Tooling/Syntax/Nodes.cpp
  clang/lib/Tooling/Syntax/Tree.cpp
  clang/unittests/Tooling/Syntax/TreeTest.cpp

Index: clang/unittests/Tooling/Syntax/TreeTest.cpp
===================================================================
--- clang/unittests/Tooling/Syntax/TreeTest.cpp
+++ clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -987,18 +987,19 @@
     | | |-IdExpression
     | | | |-NestedNameSpecifier
     | | | | |-::
-    | | | | |-IdentifierNameSpecifier
+    | | | | |-NameSpecifier
     | | | | | `-n
     | | | | |-::
-    | | | | |-IdentifierNameSpecifier
+    | | | | |-NameSpecifier
     | | | | | `-S
     | | | | |-::
-    | | | | |-SimpleTemplateNameSpecifier
-    | | | | | |-template
-    | | | | | |-ST
-    | | | | | |-<
-    | | | | | |-int
-    | | | | | `->
+    | | | | |-NameSpecifier
+    | | | | | `-SimpleTemplateSpecifier
+    | | | | |   |-template
+    | | | | |   |-ST
+    | | | | |   |-<
+    | | | | |   |-int
+    | | | | |   `->
     | | | | `-::
     | | | `-UnqualifiedId
     | | |   `-f
@@ -1009,17 +1010,18 @@
     | |-UnknownExpression
     | | |-IdExpression
     | | | |-NestedNameSpecifier
-    | | | | |-IdentifierNameSpecifier
+    | | | | |-NameSpecifier
     | | | | | `-n
     | | | | |-::
-    | | | | |-IdentifierNameSpecifier
+    | | | | |-NameSpecifier
     | | | | | `-S
     | | | | |-::
-    | | | | |-SimpleTemplateNameSpecifier
-    | | | | | |-ST
-    | | | | | |-<
-    | | | | | |-int
-    | | | | | `->
+    | | | | |-NameSpecifier
+    | | | | | `-SimpleTemplateSpecifier
+    | | | | |   |-ST
+    | | | | |   |-<
+    | | | | |   |-int
+    | | | | |   `->
     | | | | `-::
     | | | `-UnqualifiedId
     | | |   `-f
@@ -1030,13 +1032,14 @@
     | |-UnknownExpression
     | | |-IdExpression
     | | | |-NestedNameSpecifier
-    | | | | |-SimpleTemplateNameSpecifier
-    | | | | | |-ST
-    | | | | | |-<
-    | | | | | |-int
-    | | | | | `->
+    | | | | |-NameSpecifier
+    | | | | | `-SimpleTemplateSpecifier
+    | | | | |   |-ST
+    | | | | |   |-<
+    | | | | |   |-int
+    | | | | |   `->
     | | | | |-::
-    | | | | |-IdentifierNameSpecifier
+    | | | | |-NameSpecifier
     | | | | | `-S
     | | | | `-::
     | | | `-UnqualifiedId
@@ -1051,13 +1054,14 @@
     | |-UnknownExpression
     | | |-IdExpression
     | | | |-NestedNameSpecifier
-    | | | | |-SimpleTemplateNameSpecifier
-    | | | | | |-ST
-    | | | | | |-<
-    | | | | | |-int
-    | | | | | `->
+    | | | | |-NameSpecifier
+    | | | | | `-SimpleTemplateSpecifier
+    | | | | |   |-ST
+    | | | | |   |-<
+    | | | | |   |-int
+    | | | | |   `->
     | | | | |-::
-    | | | | |-IdentifierNameSpecifier
+    | | | | |-NameSpecifier
     | | | | | `-S
     | | | | `-::
     | | | |-template
@@ -1115,15 +1119,16 @@
       | |-UnknownExpression
       | | |-IdExpression
       | | | |-NestedNameSpecifier
-      | | | | |-IdentifierNameSpecifier
+      | | | | |-NameSpecifier
       | | | | | `-T
       | | | | |-::
-      | | | | |-SimpleTemplateNameSpecifier
-      | | | | | |-template
-      | | | | | |-U
-      | | | | | |-<
-      | | | | | |-int
-      | | | | | `->
+      | | | | |-NameSpecifier
+      | | | | | `-SimpleTemplateSpecifier
+      | | | | |   |-template
+      | | | | |   |-U
+      | | | | |   |-<
+      | | | | |   |-int
+      | | | | |   `->
       | | | | `-::
       | | | `-UnqualifiedId
       | | |   `-f
@@ -1134,10 +1139,10 @@
       | |-UnknownExpression
       | | |-IdExpression
       | | | |-NestedNameSpecifier
-      | | | | |-IdentifierNameSpecifier
+      | | | | |-NameSpecifier
       | | | | | `-T
       | | | | |-::
-      | | | | |-IdentifierNameSpecifier
+      | | | | |-NameSpecifier
       | | | | | `-U
       | | | | `-::
       | | | `-UnqualifiedId
@@ -1149,7 +1154,7 @@
       | |-UnknownExpression
       | | |-IdExpression
       | | | |-NestedNameSpecifier
-      | | | | |-IdentifierNameSpecifier
+      | | | | |-NameSpecifier
       | | | | | `-T
       | | | | `-::
       | | | |-template
@@ -1216,13 +1221,14 @@
     | |-UnknownExpression
     | | |-IdExpression
     | | | |-NestedNameSpecifier
-    | | | | |-DecltypeNameSpecifier
-    | | | | | |-decltype
-    | | | | | |-(
-    | | | | | |-IdExpression
-    | | | | | | `-UnqualifiedId
-    | | | | | |   `-s
-    | | | | | `-)
+    | | | | |-NameSpecifier
+    | | | | | `-DecltypeSpecifier
+    | | | | |   |-decltype
+    | | | | |   |-(
+    | | | | |   |-IdExpression
+    | | | | |   | `-UnqualifiedId
+    | | | | |   |   `-s
+    | | | | |   `-)
     | | | | `-::
     | | | `-UnqualifiedId
     | | |   `-f
Index: clang/lib/Tooling/Syntax/Tree.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Tree.cpp
+++ clang/lib/Tooling/Syntax/Tree.cpp
@@ -56,6 +56,12 @@
   return N->kind() == NodeKind::Leaf;
 }
 
+syntax::EmptyNode::EmptyNode() : Node(NodeKind::EmptyNode) {}
+
+bool syntax::EmptyNode::classof(const Node *N) {
+  return N->kind() == NodeKind::EmptyNode;
+}
+
 syntax::Node::Node(NodeKind Kind)
     : Parent(nullptr), NextSibling(nullptr), Kind(static_cast<unsigned>(Kind)),
       Role(0), Original(false), CanModify(false) {
Index: clang/lib/Tooling/Syntax/Nodes.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Nodes.cpp
+++ clang/lib/Tooling/Syntax/Nodes.cpp
@@ -12,6 +12,8 @@
 
 llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) {
   switch (K) {
+  case NodeKind::EmptyNode:
+    return OS << "EmptyNode";
   case NodeKind::Leaf:
     return OS << "Leaf";
   case NodeKind::TranslationUnit:
@@ -116,14 +118,12 @@
     return OS << "ParametersAndQualifiers";
   case NodeKind::MemberPointer:
     return OS << "MemberPointer";
-  case NodeKind::GlobalNameSpecifier:
-    return OS << "GlobalNameSpecifier";
-  case NodeKind::DecltypeNameSpecifier:
-    return OS << "DecltypeNameSpecifier";
-  case NodeKind::IdentifierNameSpecifier:
-    return OS << "IdentifierNameSpecifier";
-  case NodeKind::SimpleTemplateNameSpecifier:
-    return OS << "SimpleTemplateNameSpecifier";
+  case NodeKind::NameSpecifier:
+    return OS << "NameSpecifier";
+  case NodeKind::DecltypeSpecifier:
+    return OS << "DecltypeSpecifier";
+  case NodeKind::SimpleTemplateSpecifier:
+    return OS << "SimpleTemplateSpecifier";
   case NodeKind::NestedNameSpecifier:
     return OS << "NestedNameSpecifier";
   }
@@ -206,6 +206,15 @@
   llvm_unreachable("invalid role");
 }
 
+llvm::PointerUnion<syntax::EmptyNode *, syntax::Leaf *,
+                   syntax::DecltypeSpecifier *,
+                   syntax::SimpleTemplateSpecifier *>
+syntax::NameSpecifier::child() {
+  return llvm::PointerUnion<
+      syntax::EmptyNode *, syntax::Leaf *, syntax::DecltypeSpecifier *,
+      syntax::SimpleTemplateSpecifier *>::getFromOpaqueValue(firstChild());
+}
+
 std::vector<syntax::Leaf *> syntax::NestedNameSpecifier::delimiters() {
   std::vector<syntax::Leaf *> Children;
   for (auto *C = firstChild(); C; C = C->nextSibling()) {
Index: clang/lib/Tooling/Syntax/BuildTree.cpp
===================================================================
--- clang/lib/Tooling/Syntax/BuildTree.cpp
+++ clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -749,33 +749,6 @@
     return true;
   }
 
-  syntax::NameSpecifier *BuildNameSpecifier(const NestedNameSpecifier &NNS) {
-    switch (NNS.getKind()) {
-    case clang::NestedNameSpecifier::Global:
-      return new (allocator()) syntax::GlobalNameSpecifier;
-    case clang::NestedNameSpecifier::Namespace:
-    case clang::NestedNameSpecifier::NamespaceAlias:
-    case clang::NestedNameSpecifier::Identifier:
-      return new (allocator()) syntax::IdentifierNameSpecifier;
-    case clang::NestedNameSpecifier::TypeSpecWithTemplate:
-      return new (allocator()) syntax::SimpleTemplateNameSpecifier;
-    case clang::NestedNameSpecifier::TypeSpec: {
-      const auto *NNSType = NNS.getAsType();
-      assert(NNSType);
-      if (isa<DecltypeType>(NNSType))
-        return new (allocator()) syntax::DecltypeNameSpecifier;
-      if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>(
-              NNSType))
-        return new (allocator()) syntax::SimpleTemplateNameSpecifier;
-      return new (allocator()) syntax::IdentifierNameSpecifier;
-    }
-    case clang::NestedNameSpecifier::Super:
-      // FIXME: Support Microsoft's __super
-      llvm::report_fatal_error("We don't yet support the __super specifier",
-                               true);
-    }
-  }
-
   // FIXME: Fix `NestedNameSpecifierLoc::getLocalSourceRange` for the
   // `DependentTemplateSpecializationType` case.
   /// Given a nested-name-specifier return the range for the last name specifier
@@ -806,16 +779,76 @@
     return SR;
   }
 
+  syntax::NodeKind getNameSpecifierChildKind(const NestedNameSpecifier &NNS) {
+    switch (NNS.getKind()) {
+    case clang::NestedNameSpecifier::Global:
+      return syntax::NodeKind::EmptyNode;
+    case clang::NestedNameSpecifier::Namespace:
+    case clang::NestedNameSpecifier::NamespaceAlias:
+    case clang::NestedNameSpecifier::Identifier:
+      return syntax::NodeKind::Leaf;
+    case clang::NestedNameSpecifier::TypeSpecWithTemplate:
+      return syntax::NodeKind::SimpleTemplateSpecifier;
+    case clang::NestedNameSpecifier::TypeSpec: {
+      const auto *NNSType = NNS.getAsType();
+      assert(NNSType);
+      if (isa<DecltypeType>(NNSType))
+        return syntax::NodeKind::DecltypeSpecifier;
+      if (isa<TemplateSpecializationType, DependentTemplateSpecializationType>(
+              NNSType))
+        return syntax::NodeKind::SimpleTemplateSpecifier;
+      return syntax::NodeKind::Leaf;
+    }
+    case clang::NestedNameSpecifier::Super:
+      // FIXME: Support Microsoft's __super
+      llvm::report_fatal_error("We don't yet support the __super specifier",
+                               true);
+    }
+  }
+
+  syntax::NameSpecifier *
+  BuildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) {
+    auto *NNS = NNSLoc.getNestedNameSpecifier();
+    assert(NNS);
+    auto SR = getLocalSourceRange(NNSLoc);
+    switch (getNameSpecifierChildKind(*NNS)) {
+    case syntax::NodeKind::EmptyNode: {
+      Builder.markChild(new (allocator()) syntax::EmptyNode,
+                        syntax::NodeRole::Unknown);
+      return new (allocator()) syntax::NameSpecifier;
+    }
+    case syntax::NodeKind::Leaf: {
+      Builder.markChildToken(SR.getBegin(), syntax::NodeRole::Unknown);
+      break;
+    }
+    case syntax::NodeKind::SimpleTemplateSpecifier: {
+      auto *child = new (allocator()) syntax::SimpleTemplateSpecifier;
+      Builder.foldNode(Builder.getRange(SR), child, nullptr);
+      Builder.markChild(child, syntax::NodeRole::Unknown);
+      break;
+    }
+    case syntax::NodeKind::DecltypeSpecifier: {
+      auto *child = new (allocator()) syntax::DecltypeSpecifier;
+      Builder.foldNode(Builder.getRange(SR), child, nullptr);
+      Builder.markChild(child, syntax::NodeRole::Unknown);
+      break;
+    }
+    default:
+      llvm_unreachable("getChildKind() does not return this value");
+    }
+
+    auto *NS = new (allocator()) syntax::NameSpecifier;
+    Builder.foldNode(Builder.getRange(SR), NS, nullptr);
+    return NS;
+  }
+
   syntax::NestedNameSpecifier *
   BuildNestedNameSpecifier(const NestedNameSpecifierLoc &QualifierLoc) {
     if (!QualifierLoc)
       return nullptr;
     for (auto it = QualifierLoc; it; it = it.getPrefix()) {
-      assert(it.hasQualifier());
-      auto *NS = BuildNameSpecifier(*it.getNestedNameSpecifier());
+      auto *NS = BuildNameSpecifier(it);
       assert(NS);
-      if (!isa<syntax::GlobalNameSpecifier>(NS))
-        Builder.foldNode(Builder.getRange(getLocalSourceRange(it)), NS, it);
       Builder.markChild(NS, syntax::NodeRole::NestedNameSpecifier_specifier);
       Builder.markChildToken(it.getEndLoc(),
                              syntax::NodeRole::NestedNameSpecifier_delimiter);
Index: clang/include/clang/Tooling/Syntax/Tree.h
===================================================================
--- clang/include/clang/Tooling/Syntax/Tree.h
+++ clang/include/clang/Tooling/Syntax/Tree.h
@@ -148,6 +148,12 @@
   const syntax::Token *Tok;
 };
 
+class EmptyNode final : public Node {
+public:
+  EmptyNode();
+  static bool classof(const Node *N);
+};
+
 /// A node that has children and represents a syntactic language construct.
 class Tree : public Node {
 public:
Index: clang/include/clang/Tooling/Syntax/Nodes.h
===================================================================
--- clang/include/clang/Tooling/Syntax/Nodes.h
+++ clang/include/clang/Tooling/Syntax/Nodes.h
@@ -36,6 +36,7 @@
 /// of syntax::Node.
 enum class NodeKind : uint16_t {
   Leaf,
+  EmptyNode,
   TranslationUnit,
 
   // Expressions.
@@ -96,12 +97,12 @@
   ParametersAndQualifiers,
   MemberPointer,
   UnqualifiedId,
+
   // Nested Name Specifiers.
   NestedNameSpecifier,
-  GlobalNameSpecifier,
-  DecltypeNameSpecifier,
-  IdentifierNameSpecifier,
-  SimpleTemplateNameSpecifier
+  NameSpecifier,
+  DecltypeSpecifier,
+  SimpleTemplateSpecifier
 };
 /// For debugging purposes.
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K);
@@ -200,62 +201,34 @@
   }
 };
 
-/// 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->kind() == NodeKind::GlobalNameSpecifier ||
-           N->kind() == NodeKind::DecltypeNameSpecifier ||
-           N->kind() == NodeKind::IdentifierNameSpecifier ||
-           N->kind() == 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 {
+class DecltypeSpecifier final : public Tree {
 public:
-  GlobalNameSpecifier() : NameSpecifier(NodeKind::GlobalNameSpecifier) {}
+  DecltypeSpecifier() : Tree(NodeKind::DecltypeSpecifier) {}
   static bool classof(const Node *N) {
-    return N->kind() == NodeKind::GlobalNameSpecifier;
+    return N->kind() == NodeKind::DecltypeSpecifier;
   }
 };
 
-/// 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 {
+class SimpleTemplateSpecifier : public Tree {
 public:
-  DecltypeNameSpecifier() : NameSpecifier(NodeKind::DecltypeNameSpecifier) {}
+  SimpleTemplateSpecifier() : Tree(NodeKind::SimpleTemplateSpecifier) {}
   static bool classof(const Node *N) {
-    return N->kind() == NodeKind::DecltypeNameSpecifier;
+    return N->kind() == NodeKind::SimpleTemplateSpecifier;
   }
 };
 
-/// 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->kind() == 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 {
+/// A sequence of these specifiers make a `nested-name-specifier`.
+/// e.g. the `std` or `vector<int>` in `std::vector<int>::size`.
+class NameSpecifier final : public Tree {
 public:
-  SimpleTemplateNameSpecifier()
-      : NameSpecifier(NodeKind::SimpleTemplateNameSpecifier) {}
+  NameSpecifier() : Tree(NodeKind::NameSpecifier) {}
   static bool classof(const Node *N) {
-    return N->kind() == NodeKind::SimpleTemplateNameSpecifier;
+    return N->kind() == NodeKind::NameSpecifier;
   }
+  llvm::PointerUnion<syntax::EmptyNode *, syntax::Leaf *,
+                     syntax::DecltypeSpecifier *,
+                     syntax::SimpleTemplateSpecifier *>
+  child();
 };
 
 /// Models a `nested-name-specifier`. C++ [expr.prim.id.qual]
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D84781: Use Pointer... Eduardo Caldas via Phabricator via cfe-commits

Reply via email to