ntroduce clang_getSpellingLocation() into libclang, to provide the
location where we're spelling a token even within a
macro. clang_getInstantiationLocation() tells where we instantiated
the macro.

I'm still not thrilled with the CXSourceLocation/CXSourceRange APIs,
since they gloss over macro-instantiation information.

Take 2: this time, adjusted tests appropriately and used a "simple"
approach to the spelling location.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118495 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 496833c..4542555 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -104,8 +104,9 @@
                                           const CharSourceRange &R) {
   // We want the last character in this location, so we will adjust the
   // location accordingly.
-  // FIXME: How do do this with a macro instantiation location?
   SourceLocation EndLoc = R.getEnd();
+  if (EndLoc.isValid() && EndLoc.isMacroID())
+    EndLoc = SM.getSpellingLoc(EndLoc);
   if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) {
     unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts);
     EndLoc = EndLoc.getFileLocWithOffset(Length);
@@ -2455,6 +2456,51 @@
     *offset = SM.getDecomposedLoc(InstLoc).second;
 }
 
+void clang_getSpellingLocation(CXSourceLocation location,
+                               CXFile *file,
+                               unsigned *line,
+                               unsigned *column,
+                               unsigned *offset) {
+  SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+  if (!location.ptr_data[0] || Loc.isInvalid()) {
+    if (file)
+      *file = 0;
+    if (line)
+      *line = 0;
+    if (column)
+      *column = 0;
+    if (offset)
+      *offset = 0;
+    return;
+  }
+
+  const SourceManager &SM =
+    *static_cast<const SourceManager*>(location.ptr_data[0]);
+  SourceLocation SpellLoc = Loc;
+  if (SpellLoc.isMacroID()) {
+    SourceLocation SimpleSpellingLoc = SM.getImmediateSpellingLoc(SpellLoc);
+    if (SimpleSpellingLoc.isFileID() &&
+        SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first))
+      SpellLoc = SimpleSpellingLoc;
+    else
+      SpellLoc = SM.getInstantiationLoc(SpellLoc);
+  }
+
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
+  FileID FID = LocInfo.first;
+  unsigned FileOffset = LocInfo.second;
+
+  if (file)
+    *file = (void *)SM.getFileEntryForID(FID);
+  if (line)
+    *line = SM.getLineNumber(FID, FileOffset);
+  if (column)
+    *column = SM.getColumnNumber(FID, FileOffset);
+  if (offset)
+    *offset = FileOffset;
+}
+
 CXSourceLocation clang_getRangeStart(CXSourceRange range) {
   CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
                               range.begin_int_data };