From 14aba76042e041b2c5e439bf4ae353a0a3c7fd73 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 24 Feb 2011 02:36:08 +0000 Subject: [PATCH] Teach NestedNameSpecifier to keep track of namespace aliases the same way it keeps track of namespaces. Previously, we would map from the namespace alias to its underlying namespace when building a nested-name-specifier, losing source information in the process. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126358 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/NestedNameSpecifier.h | 54 +++++++++++------- include/clang/AST/RecursiveASTVisitor.h | 1 + include/clang/Sema/DeclSpec.h | 22 ++++++-- lib/AST/ASTContext.cpp | 10 +++- lib/AST/ItaniumMangle.cpp | 3 + lib/AST/NestedNameSpecifier.cpp | 73 +++++++++++++++++++++++-- lib/Frontend/DocumentXML.cpp | 5 ++ lib/Sema/DeclSpec.cpp | 9 +++ lib/Sema/SemaCXXScopeSpec.cpp | 9 +-- lib/Sema/SemaTemplate.cpp | 1 + lib/Sema/SemaType.cpp | 1 + lib/Sema/TreeTransform.h | 31 +++++++++++ lib/Serialization/ASTReader.cpp | 7 +++ lib/Serialization/ASTWriter.cpp | 4 ++ tools/libclang/CIndex.cpp | 6 +- 15 files changed, 199 insertions(+), 37 deletions(-) diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 99cc1f268f..88ae02c1d0 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -25,6 +25,7 @@ namespace llvm { namespace clang { class ASTContext; +class NamespaceAliasDecl; class NamespaceDecl; class IdentifierInfo; struct PrintingPolicy; @@ -41,13 +42,22 @@ class LangOptions; /// (for dependent names), or the global specifier ('::', must be the /// first specifier). class NestedNameSpecifier : public llvm::FoldingSetNode { + + /// \brief Enumeration describing + enum StoredSpecifierKind { + StoredIdentifier = 0, + StoredNamespaceOrAlias = 1, + StoredTypeSpec = 2, + StoredTypeSpecWithTemplate = 3 + }; + /// \brief The nested name specifier that precedes this nested name /// specifier. /// /// The pointer is the nested-name-specifier that precedes this /// one. The integer stores one of the first four values of type /// SpecifierKind. - llvm::PointerIntPair Prefix; + llvm::PointerIntPair Prefix; /// \brief The last component in the nested name specifier, which /// can be an identifier, a declaration, or a type. @@ -63,21 +73,23 @@ public: /// specifier. enum SpecifierKind { /// \brief An identifier, stored as an IdentifierInfo*. - Identifier = 0, - /// \brief A namespace, stored as a Namespace*. - Namespace = 1, + Identifier, + /// \brief A namespace, stored as a NamespaceDecl*. + Namespace, + /// \brief A namespace alias, stored as a NamespaceAliasDecl*. + NamespaceAlias, /// \brief A type, stored as a Type*. - TypeSpec = 2, + TypeSpec, /// \brief A type that was preceded by the 'template' keyword, /// stored as a Type*. - TypeSpecWithTemplate = 3, + TypeSpecWithTemplate, /// \brief The global specifier '::'. There is no stored value. - Global = 4 + Global }; private: /// \brief Builds the global specifier. - NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { } + NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { } /// \brief Copy constructor used internally to clone nested name /// specifiers. @@ -108,6 +120,11 @@ public: NestedNameSpecifier *Prefix, NamespaceDecl *NS); + /// \brief Builds a nested name specifier that names a namespace alias. + static NestedNameSpecifier *Create(const ASTContext &Context, + NestedNameSpecifier *Prefix, + NamespaceAliasDecl *Alias); + /// \brief Builds a nested name specifier that names a type. static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, @@ -136,16 +153,12 @@ public: NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } /// \brief Determine what kind of nested name specifier is stored. - SpecifierKind getKind() const { - if (Specifier == 0) - return Global; - return (SpecifierKind)Prefix.getInt(); - } + SpecifierKind getKind() const; /// \brief Retrieve the identifier stored in this nested name /// specifier. IdentifierInfo *getAsIdentifier() const { - if (Prefix.getInt() == Identifier) + if (Prefix.getInt() == StoredIdentifier) return (IdentifierInfo *)Specifier; return 0; @@ -153,17 +166,16 @@ public: /// \brief Retrieve the namespace stored in this nested name /// specifier. - NamespaceDecl *getAsNamespace() const { - if (Prefix.getInt() == Namespace) - return (NamespaceDecl *)Specifier; + NamespaceDecl *getAsNamespace() const; - return 0; - } + /// \brief Retrieve the namespace alias stored in this nested name + /// specifier. + NamespaceAliasDecl *getAsNamespaceAlias() const; /// \brief Retrieve the type stored in this nested name specifier. const Type *getAsType() const { - if (Prefix.getInt() == TypeSpec || - Prefix.getInt() == TypeSpecWithTemplate) + if (Prefix.getInt() == StoredTypeSpec || + Prefix.getInt() == StoredTypeSpecWithTemplate) return (const Type *)Specifier; return 0; diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 921b799b94..328a737747 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -502,6 +502,7 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifier( switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: return true; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index cb64d2585c..49efdddb77 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -34,6 +34,7 @@ namespace clang { class LangOptions; class Diagnostic; class IdentifierInfo; + class NamespaceAliasDecl; class NamespaceDecl; class NestedNameSpecifier; class Preprocessor; @@ -96,21 +97,34 @@ public: SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); /// \brief Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'namespace-or-alias::'. + /// nested-name-specifier component of the form 'namespace::'. /// /// \param Context The AST context in which this nested-name-specifier /// resides. /// /// \param Namespace The namespace. - /// FIXME: This should also permit a namespace alias. /// - /// \param NamespaceLoc The location of the namespace or namespace alias - /// name. + /// \param NamespaceLoc The location of the namespace name. /// /// \param ColonColonLoc The location of the trailing '::'. void Extend(ASTContext &Context, NamespaceDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace-alias::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Alias The namespace alias. + /// + /// \param AliasLoc The location of the namespace alias + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, SourceLocation ColonColonLoc); + /// \brief Turn this (empty) nested-name-specifier into the global /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 0b3febd0bd..9c2455034d 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2981,7 +2981,15 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { case NestedNameSpecifier::Namespace: // A namespace is canonical; build a nested-name-specifier with // this namespace and no prefix. - return NestedNameSpecifier::Create(*this, 0, NNS->getAsNamespace()); + return NestedNameSpecifier::Create(*this, 0, + NNS->getAsNamespace()->getOriginalNamespace()); + + case NestedNameSpecifier::NamespaceAlias: + // A namespace is canonical; build a nested-name-specifier with + // this namespace and no prefix. + return NestedNameSpecifier::Create(*this, 0, + NNS->getAsNamespaceAlias()->getNamespace() + ->getOriginalNamespace()); case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index e2dbb83983..939ca7a924 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -606,6 +606,9 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) { case NestedNameSpecifier::Namespace: mangleName(Qualifier->getAsNamespace()); break; + case NestedNameSpecifier::NamespaceAlias: + mangleName(Qualifier->getAsNamespaceAlias()->getNamespace()); + break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { const Type *QTy = Qualifier->getAsType(); diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 650321d76e..1b477d85a9 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -14,6 +14,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/Type.h" #include "llvm/Support/raw_ostream.h" @@ -46,7 +47,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(Identifier); + Mockup.Prefix.setInt(StoredIdentifier); Mockup.Specifier = II; return FindOrInsert(Context, Mockup); } @@ -60,11 +61,26 @@ NestedNameSpecifier::Create(const ASTContext &Context, "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(Namespace); + Mockup.Prefix.setInt(StoredNamespaceOrAlias); Mockup.Specifier = NS; return FindOrInsert(Context, Mockup); } +NestedNameSpecifier * +NestedNameSpecifier::Create(const ASTContext &Context, + NestedNameSpecifier *Prefix, + NamespaceAliasDecl *Alias) { + assert(Alias && "Namespace alias cannot be NULL"); + assert((!Prefix || + (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && + "Broken nested name specifier"); + NestedNameSpecifier Mockup; + Mockup.Prefix.setPointer(Prefix); + Mockup.Prefix.setInt(StoredNamespaceOrAlias); + Mockup.Specifier = Alias; + return FindOrInsert(Context, Mockup); +} + NestedNameSpecifier * NestedNameSpecifier::Create(const ASTContext &Context, NestedNameSpecifier *Prefix, @@ -72,7 +88,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, assert(T && "Type cannot be NULL"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec); + Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); Mockup.Specifier = const_cast(T); return FindOrInsert(Context, Mockup); } @@ -82,7 +98,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { assert(II && "Identifier cannot be NULL"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(0); - Mockup.Prefix.setInt(Identifier); + Mockup.Prefix.setInt(StoredIdentifier); Mockup.Specifier = II; return FindOrInsert(Context, Mockup); } @@ -94,6 +110,47 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { return Context.GlobalNestedNameSpecifier; } +NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { + if (Specifier == 0) + return Global; + + switch (Prefix.getInt()) { + case StoredIdentifier: + return Identifier; + + case StoredNamespaceOrAlias: + return isa(static_cast(Specifier))? Namespace + : NamespaceAlias; + + case StoredTypeSpec: + return TypeSpec; + + case StoredTypeSpecWithTemplate: + return TypeSpecWithTemplate; + } + + return Global; +} + +/// \brief Retrieve the namespace stored in this nested name +/// specifier. +NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { + if (Prefix.getInt() == StoredNamespaceOrAlias) + return dyn_cast(static_cast(Specifier)); + + return 0; +} + +/// \brief Retrieve the namespace alias stored in this nested name +/// specifier. +NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { + if (Prefix.getInt() == StoredNamespaceOrAlias) + return dyn_cast(static_cast(Specifier)); + + return 0; +} + + /// \brief Whether this nested name specifier refers to a dependent /// type or not. bool NestedNameSpecifier::isDependent() const { @@ -103,6 +160,7 @@ bool NestedNameSpecifier::isDependent() const { return true; case Namespace: + case NamespaceAlias: case Global: return false; @@ -121,6 +179,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const { return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); case Namespace: + case NamespaceAlias: case Global: return false; @@ -147,7 +206,11 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS, break; case Namespace: - OS << getAsNamespace()->getIdentifier()->getName(); + OS << getAsNamespace()->getName(); + break; + + case NamespaceAlias: + OS << getAsNamespaceAlias()->getName(); break; case Global: diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp index b24ece5119..a09db0be47 100644 --- a/lib/Frontend/DocumentXML.cpp +++ b/lib/Frontend/DocumentXML.cpp @@ -14,6 +14,7 @@ #include "clang/Frontend/DocumentXML.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringExtras.h" @@ -218,6 +219,10 @@ void DocumentXML::addPtrAttribute(const char* pAttributeName, addPtrAttribute(pAttributeName, pNNS->getAsNamespace()); break; } + case NestedNameSpecifier::NamespaceAlias: { + addPtrAttribute(pAttributeName, pNNS->getAsNamespaceAlias()); + break; + } case NestedNameSpecifier::TypeSpec: { addPtrAttribute(pAttributeName, pNNS->getAsType()); break; diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 39984974bf..f21d90f7c8 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -74,6 +74,15 @@ void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, Range.setEnd(ColonColonLoc); } +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, + SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias); + if (Range.getBegin().isInvalid()) + Range.setBegin(AliasLoc); + Range.setEnd(ColonColonLoc); +} + void CXXScopeSpec::MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc) { assert(!ScopeRep && "Already have a nested-name-specifier!?"); diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 754c52cc4a..9daec58d4e 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -139,6 +139,9 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, case NestedNameSpecifier::Namespace: return NNS->getAsNamespace(); + case NestedNameSpecifier::NamespaceAlias: + return NNS->getAsNamespaceAlias()->getNamespace(); + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { const TagType *Tag = NNS->getAsType()->getAs(); @@ -532,11 +535,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, return false; } - // FIXME: It would be nice to maintain the namespace alias name, then - // see through that alias when resolving the nested-name-specifier down to - // a declaration context. if (NamespaceAliasDecl *Alias = dyn_cast(SD)) { - SS.Extend(Context, Alias->getNamespace(), IdentifierLoc, CCLoc); + SS.Extend(Context, Alias, IdentifierLoc, CCLoc); return false; } @@ -681,6 +681,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { switch (Qualifier->getKind()) { case NestedNameSpecifier::Global: case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: // These are always namespace scopes. We never want to enter a // namespace scope from anything but a file context. return CurContext->getRedeclContext()->isFileContext(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ab6dde5eb1..d75a1f1503 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2868,6 +2868,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: return false; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d30ed74310..ba80076003 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1895,6 +1895,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: llvm_unreachable("Nested-name-specifier must name a type"); break; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 7a0754fc88..1b2822ead7 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -876,6 +876,16 @@ public: SourceRange Range, NamespaceDecl *NS); + /// \brief Build a new nested-name-specifier given the prefix and the + /// namespace alias named in the next step in the nested-name-specifier. + /// + /// By default, performs semantic analysis when building the new + /// nested-name-specifier. Subclasses may override this routine to provide + /// different behavior. + NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, + SourceRange Range, + NamespaceAliasDecl *Alias); + /// \brief Build a new nested-name-specifier given the prefix and the /// type named in the next step in the nested-name-specifier. /// @@ -2450,6 +2460,19 @@ TreeTransform::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS); } + case NestedNameSpecifier::NamespaceAlias: { + NamespaceAliasDecl *Alias + = cast_or_null( + getDerived().TransformDecl(Range.getBegin(), + NNS->getAsNamespaceAlias())); + if (!getDerived().AlwaysRebuild() && + Prefix == NNS->getPrefix() && + Alias == NNS->getAsNamespaceAlias()) + return NNS; + + return getDerived().RebuildNestedNameSpecifier(Prefix, Range, Alias); + } + case NestedNameSpecifier::Global: // There is no meaningful transformation that one could perform on the // global scope. @@ -7567,6 +7590,14 @@ TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS); } +template +NestedNameSpecifier * +TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, + SourceRange Range, + NamespaceAliasDecl *Alias) { + return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias); +} + template NestedNameSpecifier * TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 2e8e8ca67b..6f8856cd8d 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -4730,6 +4730,13 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { break; } + case NestedNameSpecifier::NamespaceAlias: { + NamespaceAliasDecl *Alias + = cast(GetDecl(Record[Idx++])); + NNS = NestedNameSpecifier::Create(*Context, Prev, Alias); + break; + } + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { const Type *T = GetType(Record[Idx++]).getTypePtrOrNull(); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index b1edf95b9f..42ca293932 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -3470,6 +3470,10 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, AddDeclRef(NNS->getAsNamespace(), Record); break; + case NestedNameSpecifier::NamespaceAlias: + AddDeclRef(NNS->getAsNamespaceAlias(), Record); + break; + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: AddTypeRef(QualType(NNS->getAsType(), 0), Record); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 328ea62f3b..c57a489d7d 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1163,11 +1163,13 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, switch (NNS->getKind()) { case NestedNameSpecifier::Namespace: - // FIXME: The token at this source location might actually have been a - // namespace alias, but we don't model that. Lame! return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU)); + case NestedNameSpecifier::NamespaceAlias: + return Visit(MakeCursorNamespaceRef(NNS->getAsNamespaceAlias(), + Range.getBegin(), TU)); + case NestedNameSpecifier::TypeSpec: { // If the type has a form where we know that the beginning of the source // range matches up with a reference cursor. Visit the appropriate reference -- 2.40.0