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 @@ -100,10 +100,9 @@ NestedNameSpecifier, UnknownNameSpecifier, GlobalNameSpecifier, - NamespaceNameSpecifier, - TypeNameSpecifier, + DecltypeNameSpecifier, IdentifierNameSpecifier, - TypeWithTemplateNameSpecifier + SimpleTemplateNameSpecifier }; /// For debugging purposes. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K); @@ -208,10 +207,9 @@ NameSpecifier(NodeKind K) : Tree(K) {} static bool classof(const Node *N) { return N->kind() == NodeKind::GlobalNameSpecifier || - N->kind() == NodeKind::TypeNameSpecifier || - N->kind() == NodeKind::NamespaceNameSpecifier || - N->kind() == NodeKind::TypeWithTemplateNameSpecifier || - N->kind() == NodeKind::UnknownNameSpecifier; + N->kind() == NodeKind::DecltypeNameSpecifier || + N->kind() == NodeKind::IdentifierNameSpecifier || + N->kind() == NodeKind::SimpleTemplateNameSpecifier; } }; @@ -225,28 +223,17 @@ } }; -/// A type name specifier, it can be of the form: `type-name::` or -/// `decltype-name::` e.g. the `string::` in `std::string::size` or the -/// `decltype(s)::` in `decltype(s)::size`. -class TypeNameSpecifier final : public NameSpecifier { +/// 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: - TypeNameSpecifier() : NameSpecifier(NodeKind::TypeNameSpecifier) {} + DecltypeNameSpecifier() : NameSpecifier(NodeKind::DecltypeNameSpecifier) {} static bool classof(const Node *N) { - return N->kind() == NodeKind::TypeNameSpecifier; + return N->kind() == NodeKind::DecltypeNameSpecifier; } }; -/// A namespace name specifier, of the form `namespace-name::` -/// e.g. the `std::` in `std::vector::size`. -class NamespaceNameSpecifier final : public NameSpecifier { -public: - NamespaceNameSpecifier() : NameSpecifier(NodeKind::NamespaceNameSpecifier) {} - static bool classof(const Node *N) { - return N->kind() == NodeKind::NamespaceNameSpecifier; - } -}; - -/// A dependent type name specifier, of the form `namespace-name::` +/// A identifier name specifier, of the form `identifier ::` /// e.g. the `std::` in `std::vector::size`. class IdentifierNameSpecifier final : public NameSpecifier { public: @@ -257,23 +244,15 @@ } }; -/// A type name specifier coming from a template instantiation. -/// e.g. the `vector::` in `std::vector::size`. -class TypeWithTemplateNameSpecifier final : public NameSpecifier { -public: - TypeWithTemplateNameSpecifier() - : NameSpecifier(NodeKind::TypeWithTemplateNameSpecifier) {} - static bool classof(const Node *N) { - return N->kind() == NodeKind::TypeWithTemplateNameSpecifier; - } -}; - -/// A name specifier we don't support yet -class UnknownNameSpecifier final : public NameSpecifier { +/// A name specifier with a simple-template-id, of the form `template_opt +/// identifier < template-args > ::` e.g. the `vector::` in +/// `std::vector::size`. +class SimpleTemplateNameSpecifier final : public NameSpecifier { public: - UnknownNameSpecifier() : NameSpecifier(NodeKind::UnknownNameSpecifier) {} + SimpleTemplateNameSpecifier() + : NameSpecifier(NodeKind::SimpleTemplateNameSpecifier) {} static bool classof(const Node *N) { - return N->kind() == NodeKind::UnknownNameSpecifier; + return N->kind() == NodeKind::SimpleTemplateNameSpecifier; } }; 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 @@ -744,23 +744,37 @@ return true; } - syntax::NameSpecifier * - BuildNameSpecifier(NestedNameSpecifier::SpecifierKind K) { - switch (K) { + bool isDecltype(const Type &T) { + return T.getTypeClass() == Type::TypeClass::Decltype; + } + + bool isTemplateInstantiation(const Type &T) { + return T.getTypeClass() == Type::TypeClass::TemplateSpecialization || + T.getTypeClass() == Type::TypeClass::DependentTemplateSpecialization; + } + + 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: - return new (allocator()) syntax::NamespaceNameSpecifier; - case clang::NestedNameSpecifier::TypeSpec: - return new (allocator()) syntax::TypeNameSpecifier; - case clang::NestedNameSpecifier::TypeSpecWithTemplate: - return new (allocator()) syntax::TypeWithTemplateNameSpecifier; 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 (isDecltype(*NNSType)) + return new (allocator()) syntax::DecltypeNameSpecifier; + if (!isTemplateInstantiation(*NNSType)) + return new (allocator()) syntax::IdentifierNameSpecifier; + return new (allocator()) syntax::SimpleTemplateNameSpecifier; + } case clang::NestedNameSpecifier::Super: // FIXME: Support Microsoft's __super - return new (allocator()) syntax::UnknownNameSpecifier; + assert(false && "We don't yet treat the __super specifier"); } } @@ -792,7 +806,9 @@ if (!QualifierLoc) return nullptr; for (auto it = QualifierLoc; it; it = it.getPrefix()) { - auto *NS = BuildNameSpecifier(it.getNestedNameSpecifier()->getKind()); + const auto *NNS = it.getNestedNameSpecifier(); + assert(NNS); + auto *NS = BuildNameSpecifier(*NNS); Builder.foldNode(Builder.getRange(getLocalSourceRange(it)), NS, nullptr); Builder.markChild(NS, syntax::NodeRole::NestedNameSpecifier_specifier); } 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 @@ -118,16 +118,12 @@ return OS << "MemberPointer"; case NodeKind::GlobalNameSpecifier: return OS << "GlobalNameSpecifier"; - case NodeKind::NamespaceNameSpecifier: - return OS << "NamespaceNameSpecifier"; - case NodeKind::TypeNameSpecifier: - return OS << "TypeNameSpecifier"; - case NodeKind::UnknownNameSpecifier: - return OS << "UnknownNameSpecifier"; + case NodeKind::DecltypeNameSpecifier: + return OS << "DecltypeNameSpecifier"; case NodeKind::IdentifierNameSpecifier: return OS << "IdentifierNameSpecifier"; - case NodeKind::TypeWithTemplateNameSpecifier: - return OS << "TypeWithTemplateNameSpecifier"; + case NodeKind::SimpleTemplateNameSpecifier: + return OS << "SimpleTemplateNameSpecifier"; case NodeKind::NestedNameSpecifier: return OS << "NestedNameSpecifier"; } diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -988,13 +988,13 @@ | | | |-NestedNameSpecifier | | | | |-GlobalNameSpecifier | | | | | `-:: - | | | | |-NamespaceNameSpecifier + | | | | |-IdentifierNameSpecifier | | | | | |-n | | | | | `-:: - | | | | |-TypeNameSpecifier + | | | | |-IdentifierNameSpecifier | | | | | |-S | | | | | `-:: - | | | | `-TypeWithTemplateNameSpecifier + | | | | `-SimpleTemplateNameSpecifier | | | | |-template | | | | |-TS | | | | |-< @@ -1010,13 +1010,13 @@ | |-UnknownExpression | | |-IdExpression | | | |-NestedNameSpecifier - | | | | |-NamespaceNameSpecifier + | | | | |-IdentifierNameSpecifier | | | | | |-n | | | | | `-:: - | | | | |-TypeNameSpecifier + | | | | |-IdentifierNameSpecifier | | | | | |-S | | | | | `-:: - | | | | `-TypeNameSpecifier + | | | | `-SimpleTemplateNameSpecifier | | | | |-TS | | | | |-< | | | | |-int @@ -1031,13 +1031,13 @@ | |-UnknownExpression | | |-IdExpression | | | |-NestedNameSpecifier - | | | | |-TypeNameSpecifier + | | | | |-SimpleTemplateNameSpecifier | | | | | |-TS | | | | | |-< | | | | | |-int | | | | | |-> | | | | | `-:: - | | | | `-TypeNameSpecifier + | | | | `-IdentifierNameSpecifier | | | | |-S | | | | `-:: | | | `-UnqualifiedId @@ -1052,13 +1052,13 @@ | |-UnknownExpression | | |-IdExpression | | | |-NestedNameSpecifier - | | | | |-TypeNameSpecifier + | | | | |-SimpleTemplateNameSpecifier | | | | | |-TS | | | | | |-< | | | | | |-int | | | | | |-> | | | | | `-:: - | | | | `-TypeNameSpecifier + | | | | `-IdentifierNameSpecifier | | | | |-S | | | | `-:: | | | |-template @@ -1116,10 +1116,10 @@ | |-UnknownExpression | | |-IdExpression | | | |-NestedNameSpecifier - | | | | |-TypeNameSpecifier + | | | | |-IdentifierNameSpecifier | | | | | |-T | | | | | `-:: - | | | | `-TypeWithTemplateNameSpecifier + | | | | `-SimpleTemplateNameSpecifier | | | | |-template | | | | |-U | | | | |-< @@ -1135,7 +1135,7 @@ | |-UnknownExpression | | |-IdExpression | | | |-NestedNameSpecifier - | | | | |-TypeNameSpecifier + | | | | |-IdentifierNameSpecifier | | | | | |-T | | | | | `-:: | | | | `-IdentifierNameSpecifier @@ -1150,7 +1150,7 @@ | |-UnknownExpression | | |-IdExpression | | | |-NestedNameSpecifier - | | | | `-TypeNameSpecifier + | | | | `-IdentifierNameSpecifier | | | | |-T | | | | `-:: | | | |-template @@ -1217,7 +1217,7 @@ | |-UnknownExpression | | |-IdExpression | | | |-NestedNameSpecifier - | | | | `-TypeNameSpecifier + | | | | `-DecltypeNameSpecifier | | | | |-decltype | | | | |-( | | | | |-IdExpression