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 @@ -174,8 +174,6 @@ ParametersAndQualifiers_trailingReturn, IdExpression_id, IdExpression_qualifier, - NestedNameSpecifier_specifier, - NestedNameSpecifier_delimiter, ParenExpression_subExpression }; /// For debugging purposes. @@ -235,14 +233,15 @@ /// Models a `nested-name-specifier`. C++ [expr.prim.id.qual] /// e.g. the `std::vector::` in `std::vector::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 specifiers(); - std::vector delimiters(); + std::vector> + specifiersAndDoubleColons(); }; /// Models an `unqualified-id`. C++ [expr.prim.id.unqual] diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h --- a/clang/include/clang/Tooling/Syntax/Tree.h +++ b/clang/include/clang/Tooling/Syntax/Tree.h @@ -214,6 +214,7 @@ /// canBeEmpty() returning `true` /// getDelimiterTokenKind() returning `,` class List : public Tree { +public: template struct ElementAndDelimiter { Element *element; Leaf *delimiter; @@ -225,6 +226,7 @@ Separated, }; + using Tree::Tree; /// Returns the elements and corresponding delimiters. Missing elements /// and delimiters are represented as null pointers. /// diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -895,9 +895,8 @@ for (auto it = QualifierLoc; it; it = it.getPrefix()) { auto *NS = BuildNameSpecifier(it); assert(NS); - 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); } Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), new (allocator()) syntax::NestedNameSpecifier, 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 @@ -200,10 +200,6 @@ 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"; } @@ -219,23 +215,29 @@ syntax::SimpleTemplateSpecifier *>::getFromOpaqueValue(firstChild()); } -std::vector syntax::NestedNameSpecifier::delimiters() { - std::vector Children; - for (auto *C = firstChild(); C; C = C->nextSibling()) { - assert(C->role() == syntax::NodeRole::NestedNameSpecifier_delimiter); - Children.push_back(llvm::cast(C)); +// We could have an interator in list to not pay memory costs of temporary +// vector +std::vector syntax::NestedNameSpecifier::specifiers() { + auto specifiersAsNodes = getElementsAsNodes(); + std::vector Children; + for (const auto &element : specifiersAsNodes) { + Children.push_back(llvm::cast(element)); } return Children; } -std::vector syntax::NestedNameSpecifier::specifiers() { - std::vector Children; - for (auto *C = firstChild(); C; C = C->nextSibling()) { - assert(C->role() == syntax::NodeRole::NestedNameSpecifier_specifier); - Children.push_back(llvm::cast(C)); +std::vector> +syntax::NestedNameSpecifier::specifiersAndDoubleColons() { + auto specifiersAsNodesAndDoubleColons = getElementsAsNodesAndDelimiters(); + std::vector> + Children; + for (const auto &specifierAndDoubleColon : specifiersAsNodesAndDoubleColons) { + Children.push_back( + {llvm::cast(specifierAndDoubleColon.element), + specifierAndDoubleColon.delimiter}); } return Children; -} +}; syntax::NestedNameSpecifier *syntax::IdExpression::qualifier() { return llvm::cast_or_null(