]> granicus.if.org Git - clang/commitdiff
Teach NestedNameSpecifier to keep track of namespace aliases the same
authorDouglas Gregor <dgregor@apple.com>
Thu, 24 Feb 2011 02:36:08 +0000 (02:36 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 24 Feb 2011 02:36:08 +0000 (02:36 +0000)
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

15 files changed:
include/clang/AST/NestedNameSpecifier.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Sema/DeclSpec.h
lib/AST/ASTContext.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/NestedNameSpecifier.cpp
lib/Frontend/DocumentXML.cpp
lib/Sema/DeclSpec.cpp
lib/Sema/SemaCXXScopeSpec.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaType.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
tools/libclang/CIndex.cpp

index 99cc1f268fb29355374e2a74db2172fad97fc33f..88ae02c1d0540783ce4bec12c211c98bfcf1d112 100644 (file)
@@ -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<NestedNameSpecifier *, 2> Prefix;
+  llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> 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;
index 921b799b94b5883a48a6115afe65dc24e4c04681..328a7377478bd7ed92138e5f671d491c6ea882b9 100644 (file)
@@ -502,6 +502,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
   switch (NNS->getKind()) {
   case NestedNameSpecifier::Identifier:
   case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
     return true;
 
index cb64d2585c54683bad21207de7d4c7cc2d6a7d03..49efdddb771bb4237ac5604c5bd0757bdeef7f4d 100644 (file)
@@ -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);
index 0b3febd0bdb28d8f964af50f1fb7dd5ea92567e8..9c2455034d6800b904fd7b0575adabd8b64c40de 100644 (file)
@@ -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: {
index e2dbb839838e01a4b1b51a02afc0935fa9e80946..939ca7a924aa03eb9c432ea4d077333ee18a5115 100644 (file)
@@ -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();
index 650321d76ee53e5055c1cda46628908a39466c63..1b477d85a94337fbac54975f7c18835371520c95 100644 (file)
@@ -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<Type*>(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<NamespaceDecl>(static_cast<NamedDecl *>(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<NamespaceDecl>(static_cast<NamedDecl *>(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<NamespaceAliasDecl>(static_cast<NamedDecl *>(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:
index b24ece5119d691d1dc61a884de0f0ec1f61fad8b..a09db0be473ec0deba452a03e596c37adc91d272 100644 (file)
@@ -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;
index 39984974bfd43c47f1edc033a3473d0e7eb78ef8..f21d90f7c8c94b84ab4941a5a8d789391669afd7 100644 (file)
@@ -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!?");
index 754c52cc4acf4be3c940f24fa0b728d8ab2594cd..9daec58d4edca5f28db52e5031f757499754e166 100644 (file)
@@ -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<TagType>();
@@ -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<NamespaceAliasDecl>(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();
index ab6dde5eb189329f5752dc5b0a6137551d2677ac..d75a1f1503d9274d43489c65e523c5042e320046 100644 (file)
@@ -2868,6 +2868,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
   switch (NNS->getKind()) {
   case NestedNameSpecifier::Identifier:
   case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
     return false;
 
index d30ed7431065cd5e5d2ad0e4d150dbe06b7b1cd3..ba80076003c9a082d81fc25a14eb94b34e73b8e6 100644 (file)
@@ -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;
index 7a0754fc883234975c27cac2173c1beadb5b3841..1b2822ead7b8f5687d40dd1ec4f53a7a85f28557 100644 (file)
@@ -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<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
     return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS);
   }
 
+  case NestedNameSpecifier::NamespaceAlias: {
+    NamespaceAliasDecl *Alias
+      = cast_or_null<NamespaceAliasDecl>(
+                                    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<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
   return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS);
 }
 
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                   SourceRange Range,
+                                                   NamespaceAliasDecl *Alias) {
+  return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias);
+}
+
 template<typename Derived>
 NestedNameSpecifier *
 TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
index 2e8e8ca67b1c661c496713efc38b30bc911a0bf6..6f8856cd8de73ec23b01d5a049e2393365536ae6 100644 (file)
@@ -4730,6 +4730,13 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
       break;
     }
 
+    case NestedNameSpecifier::NamespaceAlias: {
+      NamespaceAliasDecl *Alias
+        = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++]));
+      NNS = NestedNameSpecifier::Create(*Context, Prev, Alias);
+      break;
+    }
+
     case NestedNameSpecifier::TypeSpec:
     case NestedNameSpecifier::TypeSpecWithTemplate: {
       const Type *T = GetType(Record[Idx++]).getTypePtrOrNull();
index b1edf95b9f9700f0290c9e7307db560a4863f16b..42ca293932bfe0afd42052073defd7691be42767 100644 (file)
@@ -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);
index 328ea62f3b4401e2fc93e8f50193433cf8bd26cc..c57a489d7df294e079d53e202ae19f16b06455ea 100644 (file)
@@ -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