[clang] fdbd599 - [SyntaxTree] Implement `NestedNameSpecifier` using the `List` base API

Eduardo Caldas via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 10 06:53:32 PDT 2020


Author: Eduardo Caldas
Date: 2020-08-10T13:43:21Z
New Revision: fdbd5996533dad25f00687f27ce8e7a8b7573ba3

URL: https://github.com/llvm/llvm-project/commit/fdbd5996533dad25f00687f27ce8e7a8b7573ba3
DIFF: https://github.com/llvm/llvm-project/commit/fdbd5996533dad25f00687f27ce8e7a8b7573ba3.diff

LOG: [SyntaxTree] Implement `NestedNameSpecifier` using the `List` base API

Added: 
    

Modified: 
    clang/include/clang/Tooling/Syntax/Nodes.h
    clang/lib/Tooling/Syntax/BuildTree.cpp
    clang/lib/Tooling/Syntax/Nodes.cpp
    clang/lib/Tooling/Syntax/Tree.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h
index fc44076621d6..8e65fa1d8923 100644
--- a/clang/include/clang/Tooling/Syntax/Nodes.h
+++ b/clang/include/clang/Tooling/Syntax/Nodes.h
@@ -173,8 +173,6 @@ enum class NodeRole : uint8_t {
   ParametersAndQualifiers_trailingReturn,
   IdExpression_id,
   IdExpression_qualifier,
-  NestedNameSpecifier_specifier,
-  NestedNameSpecifier_delimiter,
   ParenExpression_subExpression
 };
 /// For debugging purposes.
@@ -262,14 +260,15 @@ class SimpleTemplateNameSpecifier final : public NameSpecifier {
 
 /// 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 {
+class NestedNameSpecifier final : public List {
 public:
-  NestedNameSpecifier() : Tree(NodeKind::NestedNameSpecifier) {}
+  NestedNameSpecifier() : List(NodeKind::NestedNameSpecifier) {}
   static bool classof(const Node *N) {
     return N->kind() <= NodeKind::NestedNameSpecifier;
   }
   std::vector<NameSpecifier *> specifiers();
-  std::vector<Leaf *> delimiters();
+  std::vector<List::ElementAndDelimiter<syntax::NameSpecifier>>
+  specifiersAndDoubleColons();
 };
 
 /// Models an `unqualified-id`. C++ [expr.prim.id.unqual]

diff  --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index 4e76b3825b6f..76b86ac6424d 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -809,9 +809,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
       if (!isa<syntax::GlobalNameSpecifier>(NS))
         Builder.foldNode(Builder.getRange(getLocalSourceRange(it)).drop_back(),
                          NS, it);
-      Builder.markChild(NS, syntax::NodeRole::NestedNameSpecifier_specifier);
-      Builder.markChildToken(it.getEndLoc(),
-                             syntax::NodeRole::NestedNameSpecifier_delimiter);
+      Builder.markChild(NS, syntax::NodeRole::List_element);
+      Builder.markChildToken(it.getEndLoc(), syntax::NodeRole::List_delimiter);
     }
     auto *NNS = new (allocator()) syntax::NestedNameSpecifier;
     Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), NNS,

diff  --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp
index 5e8deb668352..bf3c3108cb69 100644
--- a/clang/lib/Tooling/Syntax/Nodes.cpp
+++ b/clang/lib/Tooling/Syntax/Nodes.cpp
@@ -200,30 +200,32 @@ raw_ostream &syntax::operator<<(raw_ostream &OS, NodeRole R) {
     return OS << "IdExpression_id";
   case syntax::NodeRole::IdExpression_qualifier:
     return OS << "IdExpression_qualifier";
-  case syntax::NodeRole::NestedNameSpecifier_specifier:
-    return OS << "NestedNameSpecifier_specifier";
-  case syntax::NodeRole::NestedNameSpecifier_delimiter:
-    return OS << "NestedNameSpecifier_delimiter";
   case syntax::NodeRole::ParenExpression_subExpression:
     return OS << "ParenExpression_subExpression";
   }
   llvm_unreachable("invalid role");
 }
 
-std::vector<syntax::Leaf *> syntax::NestedNameSpecifier::delimiters() {
-  std::vector<syntax::Leaf *> Children;
-  for (auto *C = firstChild(); C; C = C->nextSibling()) {
-    assert(C->role() == syntax::NodeRole::NestedNameSpecifier_delimiter);
-    Children.push_back(llvm::cast<syntax::Leaf>(C));
+// We could have an interator in list to not pay memory costs of temporary
+// vector
+std::vector<syntax::NameSpecifier *> syntax::NestedNameSpecifier::specifiers() {
+  auto specifiersAsNodes = getElementsAsNodes();
+  std::vector<syntax::NameSpecifier *> Children;
+  for (const auto &element : specifiersAsNodes) {
+    Children.push_back(llvm::cast<syntax::NameSpecifier>(element));
   }
   return Children;
 }
 
-std::vector<syntax::NameSpecifier *> syntax::NestedNameSpecifier::specifiers() {
-  std::vector<syntax::NameSpecifier *> Children;
-  for (auto *C = firstChild(); C; C = C->nextSibling()) {
-    assert(C->role() == syntax::NodeRole::NestedNameSpecifier_specifier);
-    Children.push_back(cast<syntax::NameSpecifier>(C));
+std::vector<syntax::List::ElementAndDelimiter<syntax::NameSpecifier>>
+syntax::NestedNameSpecifier::specifiersAndDoubleColons() {
+  auto specifiersAsNodesAndDoubleColons = getElementsAsNodesAndDelimiters();
+  std::vector<syntax::List::ElementAndDelimiter<syntax::NameSpecifier>>
+      Children;
+  for (const auto &specifierAndDoubleColon : specifiersAsNodesAndDoubleColons) {
+    Children.push_back(
+        {llvm::cast<syntax::NameSpecifier>(specifierAndDoubleColon.element),
+         specifierAndDoubleColon.delimiter});
   }
   return Children;
 }

diff  --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp
index 6070d1603eb8..70e3c8e02783 100644
--- a/clang/lib/Tooling/Syntax/Tree.cpp
+++ b/clang/lib/Tooling/Syntax/Tree.cpp
@@ -357,21 +357,32 @@ std::vector<syntax::Node *> syntax::List::getElementsAsNodes() {
   return children;
 }
 
-// The methods below can't be implemented without information about the derived
-// list. These methods will be implemented by switching on the derived list's
-// `NodeKind`
-
 clang::tok::TokenKind syntax::List::getDelimiterTokenKind() {
-  llvm_unreachable("There are no subclasses of List, thus "
-                   "getDelimiterTokenKind() cannot be called");
+  switch (this->kind()) {
+  case NodeKind::NestedNameSpecifier:
+    return clang::tok::coloncolon;
+  default:
+    llvm_unreachable("This is not a subclass of List, thus "
+                     "getDelimiterTokenKind() cannot be called");
+  }
 }
 
 syntax::List::TerminationKind syntax::List::getTerminationKind() {
-  llvm_unreachable("There are no subclasses of List, thus getTerminationKind() "
-                   "cannot be called");
+  switch (this->kind()) {
+  case NodeKind::NestedNameSpecifier:
+    return TerminationKind::Terminated;
+  default:
+    llvm_unreachable("This is not a subclass of List, thus "
+                     "getTerminationKind() cannot be called");
+  }
 }
 
 bool syntax::List::canBeEmpty() {
-  llvm_unreachable(
-      "There are no subclasses of List, thus canBeEmpty() cannot be called");
+  switch (this->kind()) {
+  case NodeKind::NestedNameSpecifier:
+    return false;
+  default:
+    llvm_unreachable("This is not a subclass of List, thus canBeEmpty() "
+                     "cannot be called");
+  }
 }


        


More information about the cfe-commits mailing list