Retain complete source-location information for C++
nested-name-specifiers throughout the parser, and provide a new class
(NestedNameSpecifierLoc) that contains a nested-name-specifier along
with its type-source information.

Right now, this information is completely useless, because we don't
actually store the source-location information anywhere in the
AST. Call this Step 1/N.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126391 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 1b477d8..da12aa7 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 
@@ -262,3 +263,94 @@
 void NestedNameSpecifier::dump(const LangOptions &LO) {
   print(llvm::errs(), PrintingPolicy(LO));
 }
+
+unsigned 
+NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
+  assert(Qualifier && "Expected a non-NULL qualifier");
+
+  // Location of the trailing '::'.
+  unsigned Length = sizeof(unsigned);
+
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+    // Nothing more to add.
+    break;
+
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
+    // The location of the identifier or namespace name.
+    Length += sizeof(unsigned);
+    break;
+
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec:
+    // The "void*" that points at the TypeLoc data.
+    // Note: the 'template' keyword is part of the TypeLoc.
+    Length += sizeof(void *);
+    break;
+  }
+
+  return Length;
+}
+
+unsigned 
+NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
+  unsigned Length = 0;
+  for (; Qualifier; Qualifier = Qualifier->getPrefix())
+    Length += getLocalDataLength(Qualifier);
+  return Length;
+}
+
+namespace {
+  /// \brief Load a (possibly unaligned) source location from a given address
+  /// and offset.
+  SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
+    unsigned Raw;
+    memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
+    return SourceLocation::getFromRawEncoding(Raw);
+  }
+  
+  /// \brief Load a (possibly unaligned) pointer from a given address and
+  /// offset.
+  void *LoadPointer(void *Data, unsigned Offset) {
+    void *Result;
+    memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
+    return Result;
+  }
+}
+
+SourceRange NestedNameSpecifierLoc::getSourceRange() {
+  NestedNameSpecifierLoc First = *this;
+  while (NestedNameSpecifierLoc Prefix= First.getPrefix())
+    First = Prefix;
+  
+  return SourceRange(First.getLocalSourceRange().getBegin(), 
+                     getLocalSourceRange().getEnd());
+}
+
+SourceRange NestedNameSpecifierLoc::getLocalSourceRange() {
+  unsigned Offset = getDataLength(Qualifier->getPrefix());
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+    return LoadSourceLocation(Data, Offset);
+
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
+    return SourceRange(LoadSourceLocation(Data, Offset),
+                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
+
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec: {
+    // The "void*" that points at the TypeLoc data.
+    // Note: the 'template' keyword is part of the TypeLoc.
+    void *TypeData = LoadPointer(Data, Offset);
+    TypeLoc TL(Qualifier->getAsType(), TypeData);
+    return SourceRange(TL.getBeginLoc(),
+                       LoadSourceLocation(Data, Offset + sizeof(void*)));
+  }
+  }
+  
+  return SourceRange();
+}